<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://new.pvzhe.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%E6%84%A4%E6%80%92%E7%9A%84%E9%83%8E%E6%9C%97</id>
	<title>植物大战僵尸杂交版Wiki - 用户贡献 [zh-cn]</title>
	<link rel="self" type="application/atom+xml" href="https://new.pvzhe.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%E6%84%A4%E6%80%92%E7%9A%84%E9%83%8E%E6%9C%97"/>
	<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/w/%E7%89%B9%E6%AE%8A:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/%E6%84%A4%E6%80%92%E7%9A%84%E9%83%8E%E6%9C%97"/>
	<updated>2026-08-01T01:19:45Z</updated>
	<subtitle>用户贡献</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E7%94%A8%E6%88%B7:%E6%84%A4%E6%80%92%E7%9A%84%E9%83%8E%E6%9C%97&amp;diff=15422</id>
		<title>用户:愤怒的郎朗</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E7%94%A8%E6%88%B7:%E6%84%A4%E6%80%92%E7%9A%84%E9%83%8E%E6%9C%97&amp;diff=15422"/>
		<updated>2026-07-31T09:35:07Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;display: flex; justify-content: center;&amp;quot;&amp;gt;&lt;br /&gt;
{{资料卡片&lt;br /&gt;
|图片=愤怒的郎朗.jpg&lt;br /&gt;
|图片宽度=150px&lt;br /&gt;
|图片介绍=咕咕嘎嘎！&lt;br /&gt;
|标题栏颜色=red&lt;br /&gt;
|属性1=名称&lt;br /&gt;
|属性1内容=愤怒的郎朗&lt;br /&gt;
|属性2=身份&lt;br /&gt;
|属性2内容=学生&lt;br /&gt;
|属性3=入坑时间&lt;br /&gt;
|属性3内容=2025年6月&lt;br /&gt;
|属性4=最喜欢的原版植物&lt;br /&gt;
|属性4内容=坚果墙&lt;br /&gt;
|属性5=最喜欢的杂交版植物&lt;br /&gt;
|属性5内容=火爆坚果墙&lt;br /&gt;
|额外属性1=个人简介&lt;br /&gt;
|额外属性1内容=一个热爱植物大战僵尸杂交版的学生，欢迎来我的页面串门～&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
== 我的Wiki足迹 ==&lt;br /&gt;
* 我想在这个Wiki里做的事：帮助新手快速了解游戏&lt;br /&gt;
&lt;br /&gt;
== 游戏高光时刻 ==&lt;br /&gt;
* 我的最高记录：僵尸快进家时杀掉僵尸&lt;br /&gt;
* 我自创的小套路：用辣椒铲铲25阳光的植物快速升级狂热星&lt;br /&gt;
* 最近的小目标：全白卡通关所有关卡（除在线关卡）&lt;br /&gt;
&lt;br /&gt;
== 想对大家说 ==&lt;br /&gt;
如果你也喜欢和我探讨杂交版问题，咱们可以多交流～&amp;lt;br&amp;gt;&lt;br /&gt;
如果你在游戏里遇到了什么问题，也可以在这里留言，我看到就会回复。&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E5%95%8A%E5%95%8A&amp;diff=15421</id>
		<title>啊啊</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E5%95%8A%E5%95%8A&amp;diff=15421"/>
		<updated>2026-07-31T09:31:04Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​创建页面，内容为“{{#微件:啊啊}}”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#微件:啊啊}}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E5%BE%AE%E4%BB%B6:%E5%95%8A%E5%95%8A&amp;diff=15420</id>
		<title>微件:啊啊</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E5%BE%AE%E4%BB%B6:%E5%95%8A%E5%95%8A&amp;diff=15420"/>
		<updated>2026-07-31T09:30:42Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​创建页面，内容为“&amp;lt;includeonly&amp;gt; &amp;lt;div class=&amp;quot;jiaonima-widget&amp;quot;&amp;gt; &amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang=&amp;quot;zh-CN&amp;quot;&amp;gt; &amp;lt;head&amp;gt;&amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;《植物大战僵尸杂交版》是B站UP主潜艇伟伟迷制作发布的PVZ同人游戏。新增豌豆向日葵、阳光土豆雷等杂交植物，以及冰车二爷、冰车巨人等全新僵尸，含冒险、挑战等多种模式。采用现代化引…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;jiaonima-widget&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang=&amp;quot;zh-CN&amp;quot;&amp;gt; &amp;lt;head&amp;gt;&amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;《植物大战僵尸杂交版》是B站UP主潜艇伟伟迷制作发布的PVZ同人游戏。新增豌豆向日葵、阳光土豆雷等杂交植物，以及冰车二爷、冰车巨人等全新僵尸，含冒险、挑战等多种模式。采用现代化引擎重制，画质大幅提升，同时支持手机端和电脑端，为玩家带来更加精致的游戏体验。&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;canonical&amp;quot; href=&amp;quot;https://www.pvzhe.com/new&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;robots&amp;quot; content=&amp;quot;index,follow&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;baidu-site-verification&amp;quot; content=&amp;quot;codeva-d3xjz5L2TF&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;application-name&amp;quot; content=&amp;quot;pvzHE&amp;quot;&amp;gt;&amp;lt;meta property=&amp;quot;og:type&amp;quot; content=&amp;quot;website&amp;quot;&amp;gt;&amp;lt;meta property=&amp;quot;og:site_name&amp;quot; content=&amp;quot;pvzHE&amp;quot;&amp;gt;&amp;lt;meta property=&amp;quot;og:url&amp;quot; content=&amp;quot;https://www.pvzhe.com/new&amp;quot;&amp;gt;&amp;lt;meta property=&amp;quot;og:title&amp;quot; content=&amp;quot;植物大战僵尸杂交版官网 - 手机版下载 | 电脑版下载 | 辅助工具&amp;quot;&amp;gt;&amp;lt;meta property=&amp;quot;og:description&amp;quot; content=&amp;quot;《植物大战僵尸杂交版》是B站UP主潜艇伟伟迷制作发布的PVZ同人游戏。新增豌豆向日葵、阳光土豆雷等杂交植物，以及冰车二爷、冰车巨人等全新僵尸，含冒险、挑战等多种模式。采用现代化引擎重制，画质大幅提升，同时支持手机端和电脑端，为玩家带来更加精致的游戏体验。&amp;quot;&amp;gt;&amp;lt;meta property=&amp;quot;og:image&amp;quot; content=&amp;quot;https://www.pvzhe.com/pvzhe-title-screen.webp&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;keywords&amp;quot; content=&amp;quot;植物大战僵尸杂交版, PVZ杂交版, 重制版, 重置版, 潜艇伟伟迷, 手机版, 电脑版, 安卓版, PC版, windows版&amp;quot;&amp;gt;&amp;lt;meta name=&amp;quot;generator&amp;quot; content=&amp;quot;Astro v5.17.1&amp;quot;&amp;gt;&amp;lt;script async src=&amp;quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6278518012516932&amp;quot; crossorigin=&amp;quot;anonymous&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script async src=&amp;quot;https://www.googletagmanager.com/gtag/js?id=G-0T8DJE6J5J&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
			window.dataLayer = window.dataLayer || [];&lt;br /&gt;
			function gtag(){window.dataLayer.push(arguments);}&lt;br /&gt;
			gtag(&#039;js&#039;, new Date());&lt;br /&gt;
			gtag(&#039;config&#039;, &#039;G-0T8DJE6J5J&#039;);&lt;br /&gt;
		&amp;lt;/script&amp;gt;&amp;lt;title&amp;gt;植物大战僵尸杂交版官网 - 手机版下载 | 电脑版下载 | 辅助工具&amp;lt;/title&amp;gt;&amp;lt;link rel=&amp;quot;icon&amp;quot; type=&amp;quot;image/x-icon&amp;quot; href=&amp;quot;/favicon.ico&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/_astro/api-test.Bg6TfXnd.css&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/_astro/api-test.D-fy43hV.css&amp;quot;&amp;gt;&amp;lt;/head&amp;gt; &amp;lt;body&amp;gt; &amp;lt;div class=&amp;quot;min-h-screen bg-gray-100&amp;quot;&amp;gt; &amp;lt;nav class=&amp;quot;bg-gradient-to-r from-green-600 to-green-700 text-white shadow-md&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;container mx-auto px-4&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex justify-between items-center py-4&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center space-x-3&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; alt=&amp;quot;Logo&amp;quot; class=&amp;quot;w-12 h-12 p-0.5&amp;quot;&amp;gt; &amp;lt;h1 class=&amp;quot;text-xl font-bold&amp;quot;&amp;gt; 植物大战僵尸杂交版  &amp;lt;/h1&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;button class=&amp;quot;md:hidden p-4 -mr-2 rounded-lg transition-colors hover:bg-green-700&amp;quot; data-hamburger type=&amp;quot;button&amp;quot; aria-label=&amp;quot;menu&amp;quot;&amp;gt; &amp;lt;svg class=&amp;quot;w-8 h-8&amp;quot; fill=&amp;quot;none&amp;quot; stroke=&amp;quot;currentColor&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot;&amp;gt; &amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 6h16M4 12h16M4 18h16&amp;quot;&amp;gt;&amp;lt;/path&amp;gt; &amp;lt;/svg&amp;gt; &amp;lt;/button&amp;gt; &amp;lt;div class=&amp;quot;hidden md:flex space-x-6&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;/new&amp;quot; class=&amp;quot;hover:text-green-200 transition-colors py-2 font-bold border-b-2 border-white&amp;quot;&amp;gt; 杂交版  &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;/hybrid&amp;quot; class=&amp;quot;hover:text-green-200 transition-colors py-2&amp;quot;&amp;gt; 经典杂交版  &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;/shoot&amp;quot; class=&amp;quot;hover:text-green-200 transition-colors py-2&amp;quot;&amp;gt; 射击版  &amp;lt;/a&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;absolute md:hidden top-16 right-0 w-[220px] z-[999] shadow-xl transform transition-all duration-300 ease-out rounded-lg overflow-hidden hidden bg-green-50&amp;quot; data-mobile-menu&amp;gt; &amp;lt;div class=&amp;quot;py-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex flex-col divide-y divide-green-100&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;/new&amp;quot; class=&amp;quot;px-6 py-4 text-green-800 hover:bg-green-100 transition-colors duration-200 flex items-center&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;flex-1&amp;quot;&amp;gt;杂交版&amp;lt;/span&amp;gt; &amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;h-5 w-5 text-green-600&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt; &amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M9 5l7 7-7 7&amp;quot;&amp;gt;&amp;lt;/path&amp;gt; &amp;lt;/svg&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;/hybrid&amp;quot; class=&amp;quot;px-6 py-4 text-green-800 hover:bg-green-100 transition-colors duration-200 flex items-center&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;flex-1&amp;quot;&amp;gt;经典杂交版&amp;lt;/span&amp;gt; &amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;h-5 w-5 text-green-600&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt; &amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M9 5l7 7-7 7&amp;quot;&amp;gt;&amp;lt;/path&amp;gt; &amp;lt;/svg&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;/shoot&amp;quot; class=&amp;quot;px-6 py-4 text-green-800 hover:bg-green-100 transition-colors duration-200 flex items-center&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;flex-1&amp;quot;&amp;gt;射击版&amp;lt;/span&amp;gt; &amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;h-5 w-5 text-green-600&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt; &amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M9 5l7 7-7 7&amp;quot;&amp;gt;&amp;lt;/path&amp;gt; &amp;lt;/svg&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;!-- TODO: 喵伍特工半成品，暂不推出&lt;br /&gt;
									&amp;lt;a&lt;br /&gt;
										href=&amp;quot;/spycat&amp;quot;&lt;br /&gt;
										class={`px-6 py-4 ${mobileMenuItem} transition-colors duration-200 flex items-center relative whitespace-nowrap`}&lt;br /&gt;
									&amp;gt;&lt;br /&gt;
										&amp;lt;span class=&amp;quot;flex-1 whitespace-nowrap&amp;quot;&amp;gt;喵伍特工&amp;lt;/span&amp;gt;&lt;br /&gt;
										&amp;lt;span class=&amp;quot;text-xs bg-yellow-400 text-yellow-900 px-1.5 py-0.5 rounded-full font-medium mr-2&amp;quot;&amp;gt;&lt;br /&gt;
											NEW&lt;br /&gt;
										&amp;lt;/span&amp;gt;&lt;br /&gt;
										&amp;lt;svg&lt;br /&gt;
											xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot;&lt;br /&gt;
											class=`h-5 w-5 ${mobileMenuChevron}`&lt;br /&gt;
											fill=&amp;quot;none&amp;quot;&lt;br /&gt;
											viewBox=&amp;quot;0 0 24 24&amp;quot;&lt;br /&gt;
											stroke=&amp;quot;currentColor&amp;quot;&lt;br /&gt;
										&amp;gt;&lt;br /&gt;
											&amp;lt;path&lt;br /&gt;
												stroke-linecap=&amp;quot;round&amp;quot;&lt;br /&gt;
												stroke-linejoin=&amp;quot;round&amp;quot;&lt;br /&gt;
												stroke-width=&amp;quot;2&amp;quot;&lt;br /&gt;
												d=&amp;quot;M9 5l7 7-7 7&amp;quot;&lt;br /&gt;
											&amp;gt;&amp;lt;/path&amp;gt;&lt;br /&gt;
										&amp;lt;/svg&amp;gt;&lt;br /&gt;
									&amp;lt;/a&amp;gt;&lt;br /&gt;
									--&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/nav&amp;gt; &amp;lt;main&amp;gt;  &amp;lt;div class=&amp;quot;bg-white&amp;quot;&amp;gt; &amp;lt;section class=&amp;quot;relative overflow-hidden bg-gradient-to-b from-white to-gray-50&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;absolute top-20 -left-10 w-56 h-56 bg-green-100/40 rounded-full blur-3xl pointer-events-none&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;absolute bottom-10 right-0 w-64 h-64 bg-emerald-100/30 rounded-full blur-3xl pointer-events-none&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;relative container mx-auto px-4 py-12 md:py-16 max-w-3xl text-center&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;inline-flex items-center gap-2 px-4 py-1.5 bg-green-100 text-green-700 text-sm font-semibold rounded-full mb-5&amp;quot;&amp;gt; &amp;lt;svg class=&amp;quot;w-4 h-4&amp;quot; fill=&amp;quot;currentColor&amp;quot; viewBox=&amp;quot;0 0 20 20&amp;quot;&amp;gt;&amp;lt;path fill-rule=&amp;quot;evenodd&amp;quot; d=&amp;quot;M12.395 2.553a1 1 0 00-1.45-.385c-.345.23-.614.558-.822.88-.214.33-.403.713-.57 1.116-.334.804-.614 1.768-.84 2.734a31.365 31.365 0 00-.613 3.58 2.64 2.64 0 01-.945-1.067c-.328-.68-.398-1.534-.398-2.654A1 1 0 005.05 6.05 6.981 6.981 0 003 11a7 7 0 1011.95-4.95c-.592-.591-.98-.985-1.348-1.467-.363-.476-.724-1.063-1.207-2.03zM12.12 15.12A3 3 0 017 13s.879.5 2.5.5c0-1 .5-4 1.25-4.5.5 1 .786 1.293 1.371 1.879A2.99 2.99 0 0113 13a2.99 2.99 0 01-.879 2.121z&amp;quot; clip-rule=&amp;quot;evenodd&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt;&lt;br /&gt;
B站UP主 潜艇伟伟迷 作品系列&lt;br /&gt;
&amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;text-4xl md:text-6xl font-black tracking-tight mb-4 bg-gradient-to-r from-green-600 via-emerald-600 to-teal-600 bg-clip-text text-transparent&amp;quot;&amp;gt;&lt;br /&gt;
植物大战僵尸杂交版&lt;br /&gt;
&amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-base md:text-lg text-gray-400 max-w-xl mx-auto&amp;quot;&amp;gt;&lt;br /&gt;
全新引擎重制 · 画质全面升级&lt;br /&gt;
&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/section&amp;gt; &amp;lt;section class=&amp;quot;border-t border-gray-100&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;container mx-auto px-4 max-w-7xl&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex justify-center border-b border-gray-200&amp;quot;&amp;gt; &amp;lt;button type=&amp;quot;button&amp;quot; data-tab=&amp;quot;remake&amp;quot; aria-selected=&amp;quot;true&amp;quot; class=&amp;quot;px-5 py-3 text-sm font-semibold -mb-px border-b-2 transition-colors text-green-600 border-green-600&amp;quot;&amp;gt;&lt;br /&gt;
杂交版&lt;br /&gt;
&amp;lt;/button&amp;gt; &amp;lt;button type=&amp;quot;button&amp;quot; data-tab=&amp;quot;classic&amp;quot; aria-selected=&amp;quot;false&amp;quot; class=&amp;quot;px-5 py-3 text-sm font-semibold -mb-px border-b-2 border-transparent transition-colors text-gray-400 hover:text-gray-600 hover:border-gray-300&amp;quot;&amp;gt;&lt;br /&gt;
经典杂交版&lt;br /&gt;
&amp;lt;/button&amp;gt; &amp;lt;button type=&amp;quot;button&amp;quot; data-tab=&amp;quot;shoot&amp;quot; aria-selected=&amp;quot;false&amp;quot; class=&amp;quot;px-5 py-3 text-sm font-semibold -mb-px border-b-2 border-transparent transition-colors text-gray-400 hover:text-gray-600 hover:border-gray-300&amp;quot;&amp;gt;&lt;br /&gt;
射击版&lt;br /&gt;
&amp;lt;/button&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;py-10 md:py-14&amp;quot; data-content&amp;gt; &amp;lt;div class=&amp;quot;grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-12&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;relative w-full aspect-video group w-full rounded-xl shadow-lg ring-1 ring-black/5 overflow-hidden&amp;quot; data-video-player&amp;gt; &amp;lt;button type=&amp;quot;button&amp;quot; class=&amp;quot;absolute inset-0 w-full h-full p-0 m-0 border-0 bg-transparent text-left&amp;quot; aria-label=&amp;quot;播放视频&amp;quot; data-poster-button&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-title-screen.webp&amp;quot; alt=&amp;quot;视频封面&amp;quot; class=&amp;quot;w-full h-full object-cover cursor-pointer&amp;quot; loading=&amp;quot;eager&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;absolute inset-0 flex items-center justify-center transition-opacity duration-300 cursor-pointer opacity-100&amp;quot; data-overlay&amp;gt; &amp;lt;div class=&amp;quot;bg-black bg-opacity-50 rounded-full p-3 md:p-4&amp;quot;&amp;gt; &amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; class=&amp;quot;h-12 w-12 md:h-16 md:w-16 text-white&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; fill=&amp;quot;currentColor&amp;quot;&amp;gt; &amp;lt;path d=&amp;quot;M8 5v14l11-7z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt; &amp;lt;/svg&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/button&amp;gt; &amp;lt;iframe src=&amp;quot;about:blank&amp;quot; data-src=&amp;quot;https://player.bilibili.com/player.html?aid=1603128919&amp;amp;bvid=BV1um421j7gP&amp;amp;cid=1507983200&amp;quot; class=&amp;quot;absolute top-0 left-0 w-full h-full hidden&amp;quot; allow=&amp;quot;autoplay; fullscreen; picture-in-picture&amp;quot; data-iframe&amp;gt;&amp;lt;/iframe&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;script type=&amp;quot;module&amp;quot;&amp;gt;document.querySelectorAll(&amp;quot;[data-video-player]&amp;quot;).forEach(e=&amp;gt;{const r=e.querySelector(&amp;quot;[data-poster-button]&amp;quot;),t=e.querySelector(&amp;quot;[data-iframe]&amp;quot;),c=e.querySelector(&amp;quot;[data-overlay]&amp;quot;);r?.addEventListener(&amp;quot;click&amp;quot;,()=&amp;gt;{const a=t?.getAttribute(&amp;quot;data-src&amp;quot;);t&amp;amp;&amp;amp;a&amp;amp;&amp;amp;t.getAttribute(&amp;quot;src&amp;quot;)!==a&amp;amp;&amp;amp;t.setAttribute(&amp;quot;src&amp;quot;,a),t?.classList.remove(&amp;quot;hidden&amp;quot;),r?.classList.add(&amp;quot;hidden&amp;quot;),c?.classList.add(&amp;quot;opacity-0&amp;quot;)})});&amp;lt;/script&amp;gt; &amp;lt;div class=&amp;quot;flex flex-col&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-3 mb-4&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;h2 class=&amp;quot;text-2xl font-black text-gray-900&amp;quot;&amp;gt;植物大战僵尸杂交版&amp;lt;/h2&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-sm md:text-base text-gray-500 leading-relaxed mb-6&amp;quot;&amp;gt;采用全新游戏引擎重制，画质大幅提升，同时支持手机端和电脑端，在保留经典玩法的基础上加入更多创新内容，为玩家带来更加精致的游戏体验。&amp;lt;/p&amp;gt; &amp;lt;div class=&amp;quot;mt-auto space-y-4&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex flex-wrap items-center gap-3&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;https://play.pvzhe.com&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;inline-flex items-center gap-1.5 text-sm font-medium text-gray-600 hover:text-green-600 transition-colors&amp;quot;&amp;gt; &amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; 关卡创作 &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://new.pvzhe.wiki&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;inline-flex items-center gap-1.5 text-sm font-medium text-gray-600 hover:text-green-600 transition-colors&amp;quot;&amp;gt; &amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; 游戏Wiki &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://qm.qq.com/q/gqVUdXtaxO&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;inline-flex items-center gap-1.5 text-sm font-medium text-gray-600 hover:text-green-600 transition-colors&amp;quot;&amp;gt; &amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; QQ群 &amp;lt;/a&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-4 flex-wrap pt-5 border-t border-gray-100&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;制作人员&amp;lt;/span&amp;gt; &amp;lt;div class=&amp;quot;flex items-center -space-x-2&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;https://space.bilibili.com/97213827&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; title=&amp;quot;潜艇伟伟迷 · 总策划&amp;quot; class=&amp;quot;w-7 h-7 rounded-full border-2 border-white overflow-hidden hover:z-10 hover:scale-110 transition-transform shadow-sm ring-1 ring-gray-200&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;https://images.weserv.nl/?url=https://i0.hdslb.com/bfs/face/570ee03098b8fc360ad990eae6f95f76aff68bc4.jpg@240w_240h&amp;quot; class=&amp;quot;w-full h-full object-cover&amp;quot; alt=&amp;quot;潜艇伟伟迷&amp;quot;&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://space.bilibili.com/188860676&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; title=&amp;quot;虚无今天摸鱼 · 开发者&amp;quot; class=&amp;quot;w-7 h-7 rounded-full border-2 border-white overflow-hidden hover:z-10 hover:scale-110 transition-transform shadow-sm ring-1 ring-gray-200&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;https://images.weserv.nl/?url=https://i2.hdslb.com/bfs/face/b7bd655d153c802b8282fb7ebdebc04bb6262200.jpg@240w_240h&amp;quot; class=&amp;quot;w-full h-full object-cover&amp;quot; alt=&amp;quot;虚无今天摸鱼&amp;quot;&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://space.bilibili.com/102697920&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; title=&amp;quot;一只吴铭仕哒 · 美术&amp;quot; class=&amp;quot;w-7 h-7 rounded-full border-2 border-white overflow-hidden hover:z-10 hover:scale-110 transition-transform shadow-sm ring-1 ring-gray-200&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;https://images.weserv.nl/?url=https://i0.hdslb.com/bfs/face/fc4629fd89cd398bbffc878540a9afee6621230e.jpg@240w_240h&amp;quot; class=&amp;quot;w-full h-full object-cover&amp;quot; alt=&amp;quot;一只吴铭仕哒&amp;quot;&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;https://pan.quark.cn/s/327dddc7042f&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;inline-flex items-center gap-1 px-2 py-1 border border-gray-200 rounded-md text-xs text-gray-500 hover:border-green-400 hover:text-green-600 transition-colors&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-level-builder.webp&amp;quot; class=&amp;quot;w-3.5 h-3.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; 杂交版关卡构建器 &amp;lt;/a&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;mt-8&amp;quot; data-dl-section&amp;gt; &amp;lt;h3 class=&amp;quot;text-lg font-black text-gray-800 mb-4 flex items-center justify-between cursor-pointer select-none&amp;quot; data-dl-toggle&amp;gt; &amp;lt;span&amp;gt;版本下载&amp;lt;span class=&amp;quot;ml-2 text-sm font-normal text-gray-400&amp;quot;&amp;gt;50 个版本&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;svg class=&amp;quot;w-5 h-5 text-gray-400 transition-transform&amp;quot; data-dl-chevron fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M19 9l-7 7-7-7&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/h3&amp;gt; &amp;lt;div data-dl-grid class=&amp;quot;grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;https://pan.quark.cn/s/4259e472de02&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.25.5&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;px-2 py-0.5 bg-green-500 text-white text-xs rounded font-bold leading-none border border-green-500&amp;quot;&amp;gt;最新&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-7-25&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/a03f4fffc55b&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.25.5&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;安装包&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-7-25&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/515639f38eea&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.25&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;64位&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-7-19&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/3906ed8f61f4&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.24&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-7-4&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/15cd64273868&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.23&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-6-19&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/b145573873c3&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.22&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-6-7&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/267f26cf135a&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.21.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-5-28&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/a23673a672f7&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.21&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-5-24&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/38a094823d3f&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.20&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-4-30&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/a315197f5b1c&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.19.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-4-12&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/382abfe66dcf&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.19&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-4-11&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/7f112d09669a&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.18.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-4-1&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/cb97d16cb0cf&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.18&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-3-28&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/a4499f091bf2&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.17.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-3-17&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/66b0efae494a&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.17&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-3-14&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/97974f4532aa&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.16&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-2-28&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/276307904566&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.15&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-2-13&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/9d99b3ce1744&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.14&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-1-31&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/c6700866ef7e&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.13.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-1-21&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/2b6426974750&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.13&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2026-1-17&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/c2dfcc6310b9&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.12&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-12-31&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/62a731028e5f&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.11&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-12-13&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/4f9cbecc946c&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.10.5&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-11-29&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/898a77fd1f60&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.10.2&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-11-18&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/cfbacf5c9a48&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.10.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-11-16&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/62adf8e05631&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.10&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-11-15&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/1bcbd42d4761&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.9.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-11-2&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/93b7de0cc462&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.9.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-11-2&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/442a96f33eec&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.9&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-27&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/040b2bc179dc&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.9&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-27&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/2bd032460b71&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.8.2&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-5&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/4a7296071b8c&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.8.2&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-5&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/509dc03f6957&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.8.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-1&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/586faa55daa7&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.8.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-1&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/f4faec347a48&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.8&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-1&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/66ee6074f89c&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.8&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-10-1&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/7f5c8c745b50&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.7&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-9-20&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/7191bdf0305a&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.7&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-9-20&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/e775dc09de15&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.6.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-9-7&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/4ed69baf19be&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.6.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-9-7&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/90ac7f6f09c9&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.6&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-9-6&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/1cd0e8749c69&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.6&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-9-6&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/ba64fec61931&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.5.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-8-24&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/d48033581b42&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.5.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-8-24&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/41ffa16545a9&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.4&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-8-17&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/2e9b2a45aff9&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.4&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-8-17&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/0b21bf731c60&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.3&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-7-20&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/5722f810ad00&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.3&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-7-20&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/21f91a6713e7&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.2&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-7-13&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/be6f5f60b49a&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-logo.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v0.1&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;PC&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;2025-6-27&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;mt-6&amp;quot; data-tool-section&amp;gt; &amp;lt;h3 class=&amp;quot;text-lg font-black text-gray-800 mb-4 flex items-center justify-between cursor-pointer select-none&amp;quot; data-tool-toggle&amp;gt; &amp;lt;span&amp;gt;辅助工具&amp;lt;span class=&amp;quot;ml-2 text-sm font-normal text-gray-400&amp;quot;&amp;gt;2 个工具&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;svg class=&amp;quot;w-5 h-5 text-gray-400 transition-transform&amp;quot; data-tool-chevron fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M19 9l-7 7-7-7&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/h3&amp;gt; &amp;lt;div data-tool-grid class=&amp;quot;grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3&amp;quot;&amp;gt; &amp;lt;a href=&amp;quot;https://pan.quark.cn/s/327dddc7042f&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-level-builder.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;p class=&amp;quot;text-sm font-bold text-gray-900 mb-0.5&amp;quot;&amp;gt;杂交版关卡构建器&amp;lt;/p&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;v0.25.5&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;关卡制作&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;Win10/11&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;https://pan.quark.cn/s/19ef82079a5b&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt; &amp;lt;img src=&amp;quot;/pvzhe-level-builder.webp&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt; &amp;lt;p class=&amp;quot;text-sm font-bold text-gray-900 mb-0.5&amp;quot;&amp;gt;杂交版关卡构建器&amp;lt;/p&amp;gt; &amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap&amp;quot;&amp;gt; &amp;lt;span class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;v0.25.5&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;关卡制作&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;手电筒版&amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;&lt;br /&gt;
下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/svg&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/section&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;script type=&amp;quot;application/json&amp;quot; id=&amp;quot;games-data&amp;quot;&amp;gt;{&amp;quot;remake&amp;quot;:{&amp;quot;title&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;badge&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;desc&amp;quot;:&amp;quot;采用全新游戏引擎重制，画质大幅提升，同时支持手机端和电脑端，在保留经典玩法的基础上加入更多创新内容，为玩家带来更加精致的游戏体验。&amp;quot;,&amp;quot;logo&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;video&amp;quot;:{&amp;quot;poster&amp;quot;:&amp;quot;/pvzhe-title-screen.webp&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://player.bilibili.com/player.html?aid=1603128919&amp;amp;bvid=BV1um421j7gP&amp;amp;cid=1507983200&amp;quot;},&amp;quot;authors&amp;quot;:[&amp;quot;潜艇伟伟迷&amp;quot;,&amp;quot;虚无今天摸鱼&amp;quot;,&amp;quot;一只吴铭仕哒&amp;quot;],&amp;quot;downloads&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.25.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/4259e472de02&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;最新版本&amp;quot;,&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-7-25&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.25.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a03f4fffc55b&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;最新版本&amp;quot;,&amp;quot;安装包&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-7-25&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;android&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.25&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/515639f38eea&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;,&amp;quot;64位&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-7-19&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.24&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/3906ed8f61f4&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-7-4&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.23&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/15cd64273868&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-6-19&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.22&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/b145573873c3&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-6-7&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.21.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/267f26cf135a&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-5-28&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.21&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a23673a672f7&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-5-24&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.20&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/38a094823d3f&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-4-30&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.19.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a315197f5b1c&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-4-12&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.19&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/382abfe66dcf&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-4-11&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.18.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/7f112d09669a&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-4-1&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.18&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/cb97d16cb0cf&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-3-28&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.17.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a4499f091bf2&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-3-17&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.17&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/66b0efae494a&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-3-14&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.16&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/97974f4532aa&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-2-28&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.15&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/276307904566&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-2-13&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.14&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/9d99b3ce1744&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-1-31&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.13.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/c6700866ef7e&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-1-21&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.13&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/2b6426974750&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-1-17&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.12&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/c2dfcc6310b9&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-12-31&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.11&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/62a731028e5f&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-12-13&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.10.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/4f9cbecc946c&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-11-29&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.10.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/898a77fd1f60&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-11-18&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.10.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/cfbacf5c9a48&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-11-16&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.10&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/62adf8e05631&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-11-15&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.9.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/1bcbd42d4761&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-11-2&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.9.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/93b7de0cc462&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-11-2&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.9&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/442a96f33eec&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-27&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.9&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/040b2bc179dc&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-27&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.8.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/2bd032460b71&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-5&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.8.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/4a7296071b8c&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-5&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.8.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/509dc03f6957&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-1&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.8.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/586faa55daa7&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-1&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.8&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/f4faec347a48&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-1&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.8&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/66ee6074f89c&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-10-1&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.7&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/7f5c8c745b50&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-9-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.7&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/7191bdf0305a&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-9-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.6.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/e775dc09de15&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-9-7&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.6.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/4ed69baf19be&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-9-7&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.6&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/90ac7f6f09c9&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-9-6&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.6&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/1cd0e8749c69&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-9-6&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.5.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/ba64fec61931&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-8-24&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.5.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/d48033581b42&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-8-24&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.4&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/41ffa16545a9&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-8-17&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.4&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/2e9b2a45aff9&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-8-17&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.3&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/0b21bf731c60&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-7-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.3&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/5722f810ad00&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-7-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/21f91a6713e7&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-7-13&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/be6f5f60b49a&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;PC&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2025-6-27&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;}],&amp;quot;tools&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;杂交版关卡构建器&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-level-builder.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.25.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/327dddc7042f&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;关卡制作&amp;quot;,&amp;quot;Win10/11&amp;quot;]},{&amp;quot;name&amp;quot;:&amp;quot;杂交版关卡构建器&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-level-builder.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.25.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/19ef82079a5b&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;关卡制作&amp;quot;,&amp;quot;手电筒版&amp;quot;]}],&amp;quot;links&amp;quot;:[{&amp;quot;href&amp;quot;:&amp;quot;https://play.pvzhe.com&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;关卡创作&amp;quot;},{&amp;quot;href&amp;quot;:&amp;quot;https://new.pvzhe.wiki&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;游戏Wiki&amp;quot;},{&amp;quot;href&amp;quot;:&amp;quot;https://qm.qq.com/q/gqVUdXtaxO&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;QQ群&amp;quot;}]},&amp;quot;classic&amp;quot;:{&amp;quot;title&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;badge&amp;quot;:&amp;quot;经典版&amp;quot;,&amp;quot;desc&amp;quot;:&amp;quot;基于原版框架，新增豌豆向日葵、阳光土豆雷等杂交植物，还有冰车二爷、冰车巨人等全新僵尸。游戏含冒险、挑战等多种模式，玩法丰富。&amp;quot;,&amp;quot;logo&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;video&amp;quot;:{&amp;quot;poster&amp;quot;:&amp;quot;/pvzhe-title-screen.webp&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://player.bilibili.com/player.html?aid=1603128919&amp;amp;bvid=BV1um421j7gP&amp;amp;cid=1507983200&amp;quot;},&amp;quot;authors&amp;quot;:[&amp;quot;潜艇伟伟迷&amp;quot;,&amp;quot;小小咩MS&amp;quot;,&amp;quot;AXH弦&amp;quot;,&amp;quot;一只吴铭仕哒&amp;quot;],&amp;quot;downloads&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.18&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/4584878e023f&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;最新版本&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2026-7-25&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.17&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/b03cf765450f&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2026-5-9&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.16.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/34858c66234e&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2026-4-5&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.16&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/d7d2b5e1c557&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2026-4-3&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.15&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/c411469504d1&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2026-1-22&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.14&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/512402beaf57&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-12-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.13.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/c523d7bdf103&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-11-22&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.13.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/0e0d748d73a7&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-11-21&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.13&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/655ba53b3084&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-11-21&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.12&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/384745d906ea&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-9-6&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.11&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/9a92b7f3e5f3&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-8-24&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.10&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/1c976f5dc31c&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-8-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.9.9&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/e446905dbe5d&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-7-26&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.9&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/5345e30859d1&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-7-4&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.8.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a1c0cff28923&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-6-19&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.7&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/d7992a712f6b&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-5-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.6.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/ee6f1d841b1c&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-5-1&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.6&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/5b49a68731ac&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-4-19&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/97881440b387&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-4-5&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.4.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a4a43d4ea092&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-3-22&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.4&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/7767cb11b8c1&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-3-16&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.3&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/14a6b7b8fb01&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-2-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.2.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/79c83c1a6604&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-1-31&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/28b9dfd13957&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-1-28&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.1.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/00fa172fcbd5&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-1-22&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/e01169fda15c&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2025-1-18&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.0.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/5cd0ffc66fdd&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-12-21&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.0.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/907ef4a238a1&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-12-15&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.0&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/3c05a2736d70&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-12-14&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.6.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/c61ffff3f68a&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-11-2&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.6&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/d2d38fc63023&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-10-26&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.5.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/608c90747aa3&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-9-24&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/b40ef9372b17&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-9-20&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.4&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/3e9bcd0edeb0&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-9-5&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.3.7&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/7e735282ecbc&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-8-18&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.3.6&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/4fe12583e352&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-8-17&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.3.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/22bfc3717c51&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-8-12&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.3&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/549d16cf28e3&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-7-29&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/68586c1cb654&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-7-5&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/c1a75e93ecb5&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-6-13&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.0.88&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/bd821b3bb4db&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-5-17&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/882dd60a585f&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-5-8&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;1.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/082692e19a96&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-4-12&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;1.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/810df71082b1&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-4-10&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸杂交版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;1.0&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/44bceb3d7a3d&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-3-27&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;}],&amp;quot;tools&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;关卡进度修改器&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzhe-leveldata-editor.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;3.16.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/48ffd8f2a778&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;存档修改器&amp;quot;]},{&amp;quot;name&amp;quot;:&amp;quot;PVZ窗口调节工具&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvz-ws.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;1.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/509d7068e30d&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;调窗口大小&amp;quot;]},{&amp;quot;name&amp;quot;:&amp;quot;Winlator&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/winlator.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;8.4.5&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/27930cbc4298&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;手机模拟器&amp;quot;]},{&amp;quot;name&amp;quot;:&amp;quot;Magpie&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/magpie.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.11.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/5d62f89e3ca1&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;全屏工具&amp;quot;,&amp;quot;提高画质&amp;quot;]},{&amp;quot;name&amp;quot;:&amp;quot;Magpie&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/magpie.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.5.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/e057cd06de2f&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;全屏工具&amp;quot;,&amp;quot;提高画质&amp;quot;]}],&amp;quot;links&amp;quot;:[{&amp;quot;href&amp;quot;:&amp;quot;https://pvzhe.wiki/w/杂交版指南&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;游戏指南&amp;quot;},{&amp;quot;href&amp;quot;:&amp;quot;https://pvzhe.wiki&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;游戏Wiki&amp;quot;},{&amp;quot;href&amp;quot;:&amp;quot;https://qm.qq.com/q/gqVUdXtaxO&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;QQ群&amp;quot;}]},&amp;quot;shoot&amp;quot;:{&amp;quot;title&amp;quot;:&amp;quot;植物大战僵尸射击版&amp;quot;,&amp;quot;badge&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;desc&amp;quot;:&amp;quot;在经典玩法基础上融入射击元素。玩家操控小推车移动植物，通过消灭僵尸收集阳光来升级植物，冒险模式中还可提升植物攻击速度、进化植物等。&amp;quot;,&amp;quot;logo&amp;quot;:&amp;quot;/pvzsh-logo.webp&amp;quot;,&amp;quot;video&amp;quot;:{&amp;quot;poster&amp;quot;:&amp;quot;/pvzsh-title-screen.webp&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://player.bilibili.com/player.html?aid=113253019616726&amp;amp;bvid=BV1ux19YREBL&amp;amp;cid=26148864188&amp;quot;},&amp;quot;authors&amp;quot;:[&amp;quot;潜艇伟伟迷&amp;quot;,&amp;quot;虚无今天摸鱼&amp;quot;,&amp;quot;一只吴铭仕哒&amp;quot;],&amp;quot;downloads&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸射击版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzsh-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.3&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/1caff7e89442&amp;quot;,&amp;quot;tags&amp;quot;:[&amp;quot;最新版本&amp;quot;],&amp;quot;date&amp;quot;:&amp;quot;2024-11-13&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸射击版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzsh-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.2&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/1d0845507e76&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-10-11&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;植物大战僵尸射击版&amp;quot;,&amp;quot;icon&amp;quot;:&amp;quot;/pvzsh-logo.webp&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0.1&amp;quot;,&amp;quot;url&amp;quot;:&amp;quot;https://pan.quark.cn/s/a8123bf16ec3&amp;quot;,&amp;quot;tags&amp;quot;:[],&amp;quot;date&amp;quot;:&amp;quot;2024-9-30&amp;quot;,&amp;quot;platform&amp;quot;:&amp;quot;windows&amp;quot;}],&amp;quot;tools&amp;quot;:[],&amp;quot;links&amp;quot;:[{&amp;quot;href&amp;quot;:&amp;quot;https://pvzhe.wiki/w/射击版指南&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;问题指南&amp;quot;},{&amp;quot;href&amp;quot;:&amp;quot;https://qm.qq.com/q/gqVUdXtaxO&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;QQ群&amp;quot;}]}}&amp;lt;/script&amp;gt; &amp;lt;script type=&amp;quot;application/json&amp;quot; id=&amp;quot;authors-data&amp;quot;&amp;gt;{&amp;quot;潜艇伟伟迷&amp;quot;:{&amp;quot;icon&amp;quot;:&amp;quot;https://images.weserv.nl/?url=https://i0.hdslb.com/bfs/face/570ee03098b8fc360ad990eae6f95f76aff68bc4.jpg@240w_240h&amp;quot;,&amp;quot;bilibili&amp;quot;:&amp;quot;https://space.bilibili.com/97213827&amp;quot;,&amp;quot;role&amp;quot;:&amp;quot;总策划&amp;quot;},&amp;quot;小小咩MS&amp;quot;:{&amp;quot;icon&amp;quot;:&amp;quot;https://images.weserv.nl/?url=https://i1.hdslb.com/bfs/face/37d88fecfd7c3893b2466ab4a5c502793579d02f.jpg@240w_240h&amp;quot;,&amp;quot;bilibili&amp;quot;:&amp;quot;https://space.bilibili.com/262402657&amp;quot;,&amp;quot;role&amp;quot;:&amp;quot;开发者&amp;quot;},&amp;quot;AXH弦&amp;quot;:{&amp;quot;icon&amp;quot;:&amp;quot;https://images.weserv.nl/?url=https://i1.hdslb.com/bfs/face/b4e9b974d1cd7f18258c8aa7412a30dd1605a627.jpg@240w_240h&amp;quot;,&amp;quot;bilibili&amp;quot;:&amp;quot;https://space.bilibili.com/1447962088&amp;quot;,&amp;quot;role&amp;quot;:&amp;quot;技术支持&amp;quot;},&amp;quot;一只吴铭仕哒&amp;quot;:{&amp;quot;icon&amp;quot;:&amp;quot;https://images.weserv.nl/?url=https://i0.hdslb.com/bfs/face/fc4629fd89cd398bbffc878540a9afee6621230e.jpg@240w_240h&amp;quot;,&amp;quot;bilibili&amp;quot;:&amp;quot;https://space.bilibili.com/102697920&amp;quot;,&amp;quot;role&amp;quot;:&amp;quot;美术&amp;quot;},&amp;quot;虚无今天摸鱼&amp;quot;:{&amp;quot;icon&amp;quot;:&amp;quot;https://images.weserv.nl/?url=https://i2.hdslb.com/bfs/face/b7bd655d153c802b8282fb7ebdebc04bb6262200.jpg@240w_240h&amp;quot;,&amp;quot;bilibili&amp;quot;:&amp;quot;https://space.bilibili.com/188860676&amp;quot;,&amp;quot;role&amp;quot;:&amp;quot;开发者&amp;quot;}}&amp;lt;/script&amp;gt;  &amp;lt;/main&amp;gt; &amp;lt;footer class=&amp;quot;bg-gradient-to-r from-green-700 to-green-800 text-white py-4&amp;quot;&amp;gt; &amp;lt;div class=&amp;quot;container mx-auto px-4 text-center text-sm&amp;quot;&amp;gt; &amp;lt;p class=&amp;quot;mb-1&amp;quot;&amp;gt;本站点与 Electronic Arts（EA）无任何隶属关系&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;植物大战僵尸杂交版 ©2026 op@xecoy.com&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/footer&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;script type=&amp;quot;module&amp;quot;&amp;gt;const c=document.querySelector(&amp;quot;[data-hamburger]&amp;quot;),e=document.querySelector(&amp;quot;[data-mobile-menu]&amp;quot;),a=()=&amp;gt;{e?.classList.add(&amp;quot;hidden&amp;quot;)};c?.addEventListener(&amp;quot;click&amp;quot;,t=&amp;gt;{t.stopPropagation(),e?.classList.toggle(&amp;quot;hidden&amp;quot;)});e?.querySelectorAll(&amp;quot;a&amp;quot;).forEach(t=&amp;gt;{t.addEventListener(&amp;quot;click&amp;quot;,a)});document.body.addEventListener(&amp;quot;click&amp;quot;,t=&amp;gt;{if(!e||e.classList.contains(&amp;quot;hidden&amp;quot;))return;const n=t.target;n instanceof Node&amp;amp;&amp;amp;(e.contains(n)||c?.contains(n))||a()});&amp;lt;/script&amp;gt; &amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt; &amp;lt;script&amp;gt;&lt;br /&gt;
	(() =&amp;gt; {&lt;br /&gt;
		const P = (id) =&amp;gt; { const e = document.getElementById(id); try { return JSON.parse(e?.textContent || &amp;quot;{}&amp;quot;); } catch { return {}; } };&lt;br /&gt;
		const games = P(&amp;quot;games-data&amp;quot;);&lt;br /&gt;
		const authors = P(&amp;quot;authors-data&amp;quot;);&lt;br /&gt;
		const area = document.querySelector(&amp;quot;[data-content]&amp;quot;);&lt;br /&gt;
		const btns = document.querySelectorAll(&amp;quot;[data-tab]&amp;quot;);&lt;br /&gt;
		let tab = &amp;quot;remake&amp;quot;;&lt;br /&gt;
		const esc = (s) =&amp;gt; { if (s == null) return &amp;quot;&amp;quot;; const d = document.createElement(&amp;quot;div&amp;quot;); d.appendChild(document.createTextNode(String(s))); return d.innerHTML; };&lt;br /&gt;
&lt;br /&gt;
		const btnActive = &amp;quot;px-5 py-3 text-sm font-semibold -mb-px border-b-2 transition-colors text-green-600 border-green-600&amp;quot;;&lt;br /&gt;
		const btnIdle = &amp;quot;px-5 py-3 text-sm font-semibold -mb-px border-b-2 border-transparent transition-colors text-gray-400 hover:text-gray-600 hover:border-gray-300&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
		const updateBtns = () =&amp;gt; btns.forEach((b) =&amp;gt; {&lt;br /&gt;
			const t = b.getAttribute(&amp;quot;data-tab&amp;quot;);&lt;br /&gt;
			b.setAttribute(&amp;quot;aria-selected&amp;quot;, String(t === tab));&lt;br /&gt;
			b.className = t === tab ? btnActive : btnIdle;&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		const build = () =&amp;gt; {&lt;br /&gt;
			const g = games[tab];&lt;br /&gt;
			if (!g || !area) return;&lt;br /&gt;
&lt;br /&gt;
			const auth = g.authors.map((n) =&amp;gt; { const a = authors[n]; if (!a) return &amp;quot;&amp;quot;; return `&amp;lt;a href=&amp;quot;${esc(a.bilibili)}&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; title=&amp;quot;${esc(n)} · ${esc(a.role)}&amp;quot; class=&amp;quot;w-7 h-7 rounded-full border-2 border-white overflow-hidden hover:z-10 hover:scale-110 transition-transform shadow-sm ring-1 ring-gray-200&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;${esc(a.icon)}&amp;quot; class=&amp;quot;w-full h-full object-cover&amp;quot; alt=&amp;quot;${esc(n)}&amp;quot; /&amp;gt;&amp;lt;/a&amp;gt;`; }).join(&amp;quot;&amp;quot;);&lt;br /&gt;
			const lnks = g.links.map((l) =&amp;gt; `&amp;lt;a href=&amp;quot;${esc(l.href)}&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;inline-flex items-center gap-1.5 text-sm font-medium text-gray-600 hover:text-green-600 transition-colors&amp;quot;&amp;gt;&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;${esc(l.label)}&amp;lt;/a&amp;gt;`).join(&amp;quot;&amp;quot;);&lt;br /&gt;
			const tools = g.tools?.length ? `&amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap&amp;quot;&amp;gt;${(()=&amp;gt;{const s=new Set();return g.tools.filter(t=&amp;gt;s.has(t.name)?false:(s.add(t.name),true));})().slice(0,4).map((t) =&amp;gt; `&amp;lt;a href=&amp;quot;${esc(t.url)}&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;inline-flex items-center gap-1 px-2 py-1 border border-gray-200 rounded-md text-xs text-gray-500 hover:border-green-400 hover:text-green-600 transition-colors&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;${esc(t.icon)}&amp;quot; class=&amp;quot;w-3.5 h-3.5&amp;quot; alt=&amp;quot;&amp;quot; /&amp;gt;${esc(t.name)}&amp;lt;/a&amp;gt;`).join(&amp;quot;&amp;quot;)}&amp;lt;/div&amp;gt;` : &amp;quot;&amp;quot;;&lt;br /&gt;
			const dls = g.downloads?.length ? g.downloads.map((it, i) =&amp;gt; {&lt;br /&gt;
				const tags = (Array.isArray(it.tags) ? it.tags : []).filter((t) =&amp;gt; typeof t === &amp;quot;string&amp;quot; &amp;amp;&amp;amp; t !== &amp;quot;最新版本&amp;quot;);&lt;br /&gt;
				return `&amp;lt;a href=&amp;quot;${esc(it.url)}&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;${esc(it.icon)}&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap mb-0.5&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;text-sm font-bold text-gray-900&amp;quot;&amp;gt;v${esc(it.version)}&amp;lt;/span&amp;gt;${i===0?`&amp;lt;span class=&amp;quot;px-2 py-0.5 bg-green-500 text-white text-xs rounded font-bold leading-none border border-green-500&amp;quot;&amp;gt;最新&amp;lt;/span&amp;gt;`:&amp;quot;&amp;quot;}${tags.map((t)=&amp;gt;`&amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;${esc(t)}&amp;lt;/span&amp;gt;`).join(&amp;quot;&amp;quot;)}&amp;lt;/div&amp;gt;${it.date?`&amp;lt;p class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;${esc(it.date)}&amp;lt;/p&amp;gt;`:&amp;quot;&amp;quot;}&amp;lt;/div&amp;gt;&amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/a&amp;gt;`;&lt;br /&gt;
			}).join(&amp;quot;&amp;quot;) : `&amp;lt;div class=&amp;quot;col-span-full text-center py-10 text-sm text-gray-400&amp;quot;&amp;gt;暂无版本，敬请期待&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&lt;br /&gt;
			area.innerHTML = `&lt;br /&gt;
				&amp;lt;div class=&amp;quot;grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-12&amp;quot;&amp;gt;&lt;br /&gt;
					&amp;lt;div class=&amp;quot;rounded-xl shadow-lg ring-1 ring-black/5 overflow-hidden relative aspect-video&amp;quot; data-vp-host&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
					&amp;lt;div class=&amp;quot;flex flex-col&amp;quot;&amp;gt;&lt;br /&gt;
						&amp;lt;div class=&amp;quot;flex items-center gap-3 mb-4&amp;quot;&amp;gt;&lt;br /&gt;
							&amp;lt;img src=&amp;quot;${esc(g.logo)}&amp;quot; class=&amp;quot;w-8 h-8&amp;quot; alt=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;
							&amp;lt;h2 class=&amp;quot;text-2xl font-black text-gray-900&amp;quot;&amp;gt;${esc(g.title)}&amp;lt;/h2&amp;gt;&lt;br /&gt;
							${g.badge?`&amp;lt;span class=&amp;quot;px-2 text-xs font-bold rounded-full bg-green-100 text-green-700&amp;quot;&amp;gt;${esc(g.badge)}&amp;lt;/span&amp;gt;`:&amp;quot;&amp;quot;}&lt;br /&gt;
						&amp;lt;/div&amp;gt;&lt;br /&gt;
						&amp;lt;p class=&amp;quot;text-sm md:text-base text-gray-500 leading-relaxed mb-6&amp;quot;&amp;gt;${esc(g.desc)}&amp;lt;/p&amp;gt;&lt;br /&gt;
						&amp;lt;div class=&amp;quot;mt-auto space-y-4&amp;quot;&amp;gt;&lt;br /&gt;
							&amp;lt;div class=&amp;quot;flex flex-wrap items-center gap-3&amp;quot;&amp;gt;${lnks}&amp;lt;/div&amp;gt;&lt;br /&gt;
						&amp;lt;div class=&amp;quot;flex items-center gap-4 flex-wrap pt-5 border-t border-gray-100&amp;quot;&amp;gt;&lt;br /&gt;
							&amp;lt;span class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;制作人员&amp;lt;/span&amp;gt;&lt;br /&gt;
							&amp;lt;div class=&amp;quot;flex items-center -space-x-2&amp;quot;&amp;gt;${auth}&amp;lt;/div&amp;gt;&lt;br /&gt;
								${tools}&lt;br /&gt;
							&amp;lt;/div&amp;gt;&lt;br /&gt;
						&amp;lt;/div&amp;gt;&lt;br /&gt;
					&amp;lt;/div&amp;gt;&lt;br /&gt;
				&amp;lt;/div&amp;gt;&lt;br /&gt;
				&amp;lt;div class=&amp;quot;mt-8&amp;quot; data-dl-section&amp;gt;&lt;br /&gt;
					&amp;lt;h3 class=&amp;quot;text-lg font-black text-gray-800 mb-4 flex items-center justify-between cursor-pointer select-none&amp;quot; data-dl-toggle&amp;gt;&lt;br /&gt;
						&amp;lt;span&amp;gt;版本下载&amp;lt;span class=&amp;quot;ml-2 text-sm font-normal text-gray-400&amp;quot;&amp;gt;${g.downloads?.length??0} 个版本&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
						&amp;lt;svg class=&amp;quot;w-5 h-5 text-gray-400 transition-transform&amp;quot; data-dl-chevron fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M19 9l-7 7-7-7&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&lt;br /&gt;
					&amp;lt;/h3&amp;gt;&lt;br /&gt;
					&amp;lt;div data-dl-grid class=&amp;quot;grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3&amp;quot;&amp;gt;${dls}&amp;lt;/div&amp;gt;&lt;br /&gt;
				&amp;lt;/div&amp;gt;&lt;br /&gt;
				${g.tools?.length ? `&amp;lt;div class=&amp;quot;mt-6&amp;quot; data-tool-section&amp;gt;&amp;lt;h3 class=&amp;quot;text-lg font-black text-gray-800 mb-4 flex items-center justify-between cursor-pointer select-none&amp;quot; data-tool-toggle&amp;gt;&amp;lt;span&amp;gt;辅助工具&amp;lt;span class=&amp;quot;ml-2 text-sm font-normal text-gray-400&amp;quot;&amp;gt;${g.tools.length} 个工具&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;svg class=&amp;quot;w-5 h-5 text-gray-400 transition-transform&amp;quot; data-tool-chevron fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M19 9l-7 7-7-7&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/h3&amp;gt;&amp;lt;div data-tool-grid class=&amp;quot;grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3&amp;quot;&amp;gt;${g.tools.map((t) =&amp;gt; {const tgs=(Array.isArray(t.tags)?t.tags:[]).filter((tg)=&amp;gt;typeof tg===&amp;quot;string&amp;quot;);return `&amp;lt;a href=&amp;quot;${esc(t.url)}&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noreferrer&amp;quot; class=&amp;quot;group bg-white border border-gray-200 rounded-xl p-3 md:p-4 hover:border-green-400 hover:shadow-sm transition-all&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;flex items-start gap-2.5&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;${esc(t.icon)}&amp;quot; class=&amp;quot;w-8 h-8 flex-shrink-0 mt-0.5&amp;quot; alt=&amp;quot;&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;flex-1 min-w-0 flex items-center justify-between gap-2&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;min-w-0&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;text-sm font-bold text-gray-900 mb-0.5&amp;quot;&amp;gt;${esc(t.name)}&amp;lt;/p&amp;gt;&amp;lt;div class=&amp;quot;flex items-center gap-1.5 flex-wrap&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;text-xs text-gray-400&amp;quot;&amp;gt;v${esc(t.version)}&amp;lt;/span&amp;gt;${tgs.map((tg)=&amp;gt;`&amp;lt;span class=&amp;quot;px-2 py-0.5 border border-green-300 text-green-700 text-xs rounded font-medium leading-none&amp;quot;&amp;gt;${esc(tg)}&amp;lt;/span&amp;gt;`).join(&amp;quot;&amp;quot;)}&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span class=&amp;quot;inline-flex items-center gap-0.5 text-sm font-semibold text-green-600 group-hover:translate-x-0.5 transition-transform shrink-0 pt-0.5&amp;quot;&amp;gt;下载&amp;lt;svg class=&amp;quot;w-3.5 h-3.5&amp;quot; fill=&amp;quot;none&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; stroke=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; stroke-width=&amp;quot;2&amp;quot; d=&amp;quot;M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/a&amp;gt;`}).join(&amp;quot;&amp;quot;)}&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;` : &amp;quot;&amp;quot;}&lt;br /&gt;
			`;&lt;br /&gt;
&lt;br /&gt;
			const vp = area.querySelector(&amp;quot;[data-vp-host]&amp;quot;);&lt;br /&gt;
			if (vp &amp;amp;&amp;amp; g.video) {&lt;br /&gt;
				vp.innerHTML = `&amp;lt;button type=&amp;quot;button&amp;quot; class=&amp;quot;absolute inset-0 w-full h-full p-0 m-0 border-0 bg-transparent text-left&amp;quot; aria-label=&amp;quot;播放视频&amp;quot; data-vp-btn&amp;gt;&amp;lt;img src=&amp;quot;${esc(g.video.poster)}&amp;quot; class=&amp;quot;w-full h-full object-cover cursor-pointer&amp;quot; loading=&amp;quot;eager&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;absolute inset-0 flex items-center justify-center transition-opacity duration-300 cursor-pointer opacity-100&amp;quot; data-vp-overlay&amp;gt;&amp;lt;div class=&amp;quot;bg-black bg-opacity-50 rounded-full p-4&amp;quot;&amp;gt;&amp;lt;svg class=&amp;quot;h-12 w-12 md:h-16 md:w-16 text-white&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; fill=&amp;quot;currentColor&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M8 5v14l11-7z&amp;quot;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;iframe src=&amp;quot;about:blank&amp;quot; data-vp-src=&amp;quot;${esc(g.video.url)}&amp;quot; class=&amp;quot;absolute top-0 left-0 w-full h-full hidden&amp;quot; data-vp-iframe allow=&amp;quot;autoplay; fullscreen; picture-in-picture&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;`;&lt;br /&gt;
				const btn = vp.querySelector(&amp;quot;[data-vp-btn]&amp;quot;);&lt;br /&gt;
				const iframe = vp.querySelector(&amp;quot;[data-vp-iframe]&amp;quot;);&lt;br /&gt;
				const play = () =&amp;gt; { iframe.src = iframe.getAttribute(&amp;quot;data-vp-src&amp;quot;)||&amp;quot;&amp;quot;; iframe.classList.remove(&amp;quot;hidden&amp;quot;); btn?.classList.add(&amp;quot;hidden&amp;quot;); };&lt;br /&gt;
				btn?.addEventListener(&amp;quot;click&amp;quot;, play);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		btns.forEach((b) =&amp;gt; b.addEventListener(&amp;quot;click&amp;quot;, () =&amp;gt; {&lt;br /&gt;
			const t = b.getAttribute(&amp;quot;data-tab&amp;quot;);&lt;br /&gt;
			if (!t || t === tab) return;&lt;br /&gt;
			tab = t; updateBtns(); build();&lt;br /&gt;
		}));&lt;br /&gt;
		updateBtns();&lt;br /&gt;
&lt;br /&gt;
		document.addEventListener(&amp;quot;click&amp;quot;, (e) =&amp;gt; {&lt;br /&gt;
			const dlToggle = e.target.closest(&amp;quot;[data-dl-toggle]&amp;quot;);&lt;br /&gt;
			if (dlToggle) {&lt;br /&gt;
				const section = dlToggle.closest(&amp;quot;[data-dl-section]&amp;quot;);&lt;br /&gt;
				const grid = section?.querySelector(&amp;quot;[data-dl-grid]&amp;quot;);&lt;br /&gt;
				const chevron = dlToggle.querySelector(&amp;quot;[data-dl-chevron]&amp;quot;);&lt;br /&gt;
				if (grid) { grid.classList.toggle(&amp;quot;hidden&amp;quot;); chevron?.classList.toggle(&amp;quot;rotate-180&amp;quot;); }&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			const toolToggle = e.target.closest(&amp;quot;[data-tool-toggle]&amp;quot;);&lt;br /&gt;
			if (toolToggle) {&lt;br /&gt;
				const section = toolToggle.closest(&amp;quot;[data-tool-section]&amp;quot;);&lt;br /&gt;
				const grid = section?.querySelector(&amp;quot;[data-tool-grid]&amp;quot;);&lt;br /&gt;
				const chevron = toolToggle.querySelector(&amp;quot;[data-tool-chevron]&amp;quot;);&lt;br /&gt;
				if (grid) { grid.classList.toggle(&amp;quot;hidden&amp;quot;); chevron?.classList.toggle(&amp;quot;rotate-180&amp;quot;); }&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
	})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15419</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15419"/>
		<updated>2026-07-31T09:19:51Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户子页面保护 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
        var isSubpage = pageTitle.indexOf(&#039;/&#039;) !== -1;&lt;br /&gt;
&lt;br /&gt;
        // 如果是子页面，且当前用户不是页面所有者也不是管理员&lt;br /&gt;
        if (isSubpage) {&lt;br /&gt;
            var pageOwner = pageTitle.split(&#039;/&#039;)[0];&lt;br /&gt;
            var isAdmin = $.inArray(&#039;sysop&#039;, mw.config.get(&#039;wgUserGroups&#039;)) !== -1;&lt;br /&gt;
            var isOwner = currentUser === pageOwner;&lt;br /&gt;
&lt;br /&gt;
            if (!isOwner &amp;amp;&amp;amp; !isAdmin) {&lt;br /&gt;
                // 隐藏编辑按钮&lt;br /&gt;
                $(&#039;#ca-edit, #ca-ve-edit, .mw-editsection, #ca-talk, #ca-addsection&#039;).remove();&lt;br /&gt;
&lt;br /&gt;
                // 如果是编辑页面，重定向回查看页面&lt;br /&gt;
                if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
                    alert(&#039;⚠️ 你只能编辑自己的用户子页面！&#039;);&lt;br /&gt;
                    window.location.href = mw.util.getUrl(pageTitle);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 在页面顶部显示提示&lt;br /&gt;
                if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
                    var $warning = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        style: &#039;background:#fff3e0;border:1px solid #FF9800;padding:8px 15px;border-radius:8px;margin:10px 0;font-size:13px;color:#e65100;&#039;,&lt;br /&gt;
                        text: &#039;🔒 这是 &#039; + pageOwner + &#039; 的个人子页面，仅本人和管理员可编辑。&#039;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).prepend($warning);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 锁定页面交互&lt;br /&gt;
                $(&#039;body&#039;).addClass(&#039;user-subpage-locked&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E7%94%A8%E6%88%B7:%E9%A3%98%E7%8C%AB%E7%8C%AB/friendrequests&amp;diff=15417</id>
		<title>用户:飘猫猫/friendrequests</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E7%94%A8%E6%88%B7:%E9%A3%98%E7%8C%AB%E7%8C%AB/friendrequests&amp;diff=15417"/>
		<updated>2026-07-31T09:11:12Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​愤怒的郎朗 发送了好友请求&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;from&amp;quot;: &amp;quot;愤怒的郎朗&amp;quot;,&lt;br /&gt;
    &amp;quot;time&amp;quot;: 1785489070339&lt;br /&gt;
  }&lt;br /&gt;
]&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15416</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15416"/>
		<updated>2026-07-31T09:10:37Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* 电脑端样式 */&lt;br /&gt;
.responsive-two-columns .left-col {&lt;br /&gt;
    width: 320px;&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns .right-col {&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
    padding-left: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 新增：响应式图片卡片样式 */&lt;br /&gt;
.gallery-card {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);  /* 一行两个，减去gap的一半 */&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card-small {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);&lt;br /&gt;
    max-width: 150px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card img,&lt;br /&gt;
.gallery-card-small img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.image-overlay {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 30px;&lt;br /&gt;
    left: 10px;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    color: white;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.flex-gallery {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: flex-start;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    align-items: flex-start;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 手机端响应式（768px以下） === */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    /* 两栏布局变单栏 */&lt;br /&gt;
    .responsive-two-columns,&lt;br /&gt;
    .responsive-two-columns tbody,&lt;br /&gt;
    .responsive-two-columns tr,&lt;br /&gt;
    .responsive-two-columns td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns .right-col {&lt;br /&gt;
        padding-left: 0;&lt;br /&gt;
        margin-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns img {&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* 画廊卡片保持一行两个 */&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: calc(50% - 5px);&lt;br /&gt;
        max-width: none;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* PVZ导航：改为Flex布局，一行三个 */&lt;br /&gt;
    .pvz-navigation {&lt;br /&gt;
        float: none;&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table {&lt;br /&gt;
        display: flex;&lt;br /&gt;
        flex-wrap: wrap;&lt;br /&gt;
        justify-content: center;&lt;br /&gt;
        gap: 5px;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tbody {&lt;br /&gt;
        display: contents;  /* 关键！让tbody不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tr {&lt;br /&gt;
        display: contents;  /* 关键！让tr不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        flex: 0 0 calc(33.33% - 5px);  /* 固定宽度一行三个 */&lt;br /&gt;
        width: auto !important;&lt;br /&gt;
        padding: 4px;&lt;br /&gt;
        box-sizing: border-box;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td img {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
        max-width: 120px;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-title {&lt;br /&gt;
        font-size: 1.2em;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 超小屏幕（宽度小于480px）时改为一行一个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 只有带链接且不在card/轮播内的图片才有悬停放大效果 */&lt;br /&gt;
a img {&lt;br /&gt;
    transition: transform 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a img:hover {&lt;br /&gt;
    transform: scale(1.08);&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 精确排除card模板和轮播图 - 不使用慢速选择器 */&lt;br /&gt;
.card a img,&lt;br /&gt;
.swiper a img,&lt;br /&gt;
.carousel a img,&lt;br /&gt;
.slider a img,&lt;br /&gt;
.owl-carousel a img,&lt;br /&gt;
.flexslider a img {&lt;br /&gt;
    transition: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.card a img:hover,&lt;br /&gt;
.swiper a img:hover,&lt;br /&gt;
.carousel a img:hover,&lt;br /&gt;
.slider a img:hover,&lt;br /&gt;
.owl-carousel a img:hover,&lt;br /&gt;
.flexslider a img:hover {&lt;br /&gt;
    transform: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 图片点击受击缩小 */&lt;br /&gt;
a img:active {&lt;br /&gt;
    transform: scale(0.92);&lt;br /&gt;
    transition: transform 0.1s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 表格响应式：电脑一行5个，手机自动换行 === */&lt;br /&gt;
&lt;br /&gt;
/* 电脑端：保持原样，固定5列 */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    width: auto;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    width: 20%;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手机端：表格变成弹性布局，自动换行 */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 5px;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid tbody,&lt;br /&gt;
  .responsive-fixed-grid tr {&lt;br /&gt;
    display: contents;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    display: block;&lt;br /&gt;
    flex: 0 1 auto;&lt;br /&gt;
    max-width: calc(33.33% - 6px);&lt;br /&gt;
    width: auto;&lt;br /&gt;
    padding: 3px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 更小屏幕：一行2个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    max-width: calc(50% - 5px);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    max-width: 750px;&lt;br /&gt;
}&lt;br /&gt;
/* 让所有图片都能响应式缩放 */&lt;br /&gt;
img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns {&lt;br /&gt;
    padding-left: 50px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        padding-left: 0 !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* === 首页表格左偏移（仅电脑端）=== */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        margin-left: -50px !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
/* 等级颜色 */&lt;br /&gt;
.bronze-user   { color: #CD7F32 !important; font-weight: bold; }&lt;br /&gt;
.silver-user   { color: #0000FF !important; font-weight: bold; }&lt;br /&gt;
.platinum-user { color: #EE82EE !important; font-weight: bold; }&lt;br /&gt;
.gold-user     { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
.rainbow-user  { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
&lt;br /&gt;
/* 状态圆点 */&lt;br /&gt;
.user-status-dot {&lt;br /&gt;
    display: inline-block; width: 8px; height: 8px;&lt;br /&gt;
    border-radius: 50%; margin-left: 4px; vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.status-online  { background-color: #4CAF50; }&lt;br /&gt;
.status-away    { background-color: #FF9800; }&lt;br /&gt;
.status-offline { background-color: #9E9E9E; }&lt;br /&gt;
&lt;br /&gt;
/* 师徒标签 */&lt;br /&gt;
.user-tag {&lt;br /&gt;
    display: inline-block; font-size: 0.75em; padding: 0px 4px;&lt;br /&gt;
    margin-left: 4px; border-radius: 3px; vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
.user-tag-mentor { background: #4CAF50; color: white; }&lt;br /&gt;
.user-tag-newbie { background: #FF9800; color: white; }&lt;br /&gt;
&lt;br /&gt;
/* 等级图标 */&lt;br /&gt;
.user-level-icons {&lt;br /&gt;
    margin-left: 2px; font-size: 0.9em; vertical-align: middle;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡片筛选隐藏 */&lt;br /&gt;
.pvzhe-card.hidden-card { display: none; }&lt;br /&gt;
&lt;br /&gt;
/* 编辑数昵称标签 */&lt;br /&gt;
.user-title-tag {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    font-size: 0.75em;&lt;br /&gt;
    padding: 1px 5px;&lt;br /&gt;
    margin-left: 4px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    background: #f0f0f0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 版本更新公告弹窗样式 */&lt;br /&gt;
.update-notice-content {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.update-version {&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #2c3e50;&lt;br /&gt;
    margin-bottom: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
.update-date {&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    margin-bottom: 15px;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul li {&lt;br /&gt;
    padding: 6px 0;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 返回顶部按钮 */&lt;br /&gt;
#back-to-top {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 40px;&lt;br /&gt;
    right: 30px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 45px;&lt;br /&gt;
    height: 45px;&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: none;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
    box-shadow: 0 2px 10px rgba(0,0,0,0.3);&lt;br /&gt;
    transition: opacity 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
#back-to-top:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
    transform: scale(1.1);&lt;br /&gt;
}&lt;br /&gt;
/* 私信系统样式 */&lt;br /&gt;
.msg-badge {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 20px;&lt;br /&gt;
    background: #f44336;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 20px;&lt;br /&gt;
    height: 20px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 20px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 100001;&lt;br /&gt;
    display: none;&lt;br /&gt;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);&lt;br /&gt;
    animation: msgPulse 2s infinite;&lt;br /&gt;
}&lt;br /&gt;
@keyframes msgPulse {&lt;br /&gt;
    0%, 100% { box-shadow: 0 2px 6px rgba(0,0,0,0.3); }&lt;br /&gt;
    50% { box-shadow: 0 2px 16px rgba(244,67,54,0.6); }&lt;br /&gt;
}&lt;br /&gt;
.msg-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.msg-box {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.msg-item {&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    padding: 10px 0;&lt;br /&gt;
}&lt;br /&gt;
.msg-sender {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.msg-time {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
}&lt;br /&gt;
.msg-text {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions button {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    padding: 2px 8px;&lt;br /&gt;
    margin-right: 5px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    background: #f9f9f9;&lt;br /&gt;
}&lt;br /&gt;
.msg-item.unread {&lt;br /&gt;
    background: #fffde7;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 2px 10px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #4CAF50;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
}&lt;br /&gt;
.msg-textarea {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    resize: vertical;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    margin-top: 10px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
.msg-loading {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
/* 好友系统 */&lt;br /&gt;
.friend-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.friend-add-btn { background: #4CAF50; }&lt;br /&gt;
.friend-add-btn:hover { background: #45a049; }&lt;br /&gt;
.friend-added-btn { background: #2196F3; }&lt;br /&gt;
.friend-added-btn:hover { background: #1e88e5; }&lt;br /&gt;
.friend-pending-btn { background: #FF9800; cursor: not-allowed; }&lt;br /&gt;
.friend-accept-btn { background: #4CAF50; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; margin-right: 5px; }&lt;br /&gt;
.friend-reject-btn { background: #f44336; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; }&lt;br /&gt;
.friend-list-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    margin: 4px 8px 4px 0;&lt;br /&gt;
    padding: 4px 10px;&lt;br /&gt;
    background: #f5f5f5;&lt;br /&gt;
    border-radius: 16px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item a { text-decoration: none; }&lt;br /&gt;
.friend-list-item .friend-remove {&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item .friend-remove:hover { color: #f44336; }&lt;br /&gt;
.friend-request-item {&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
}&lt;br /&gt;
.friend-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0; left: 0;&lt;br /&gt;
    width: 100%; height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.friend-dialog {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 450px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.friend-count {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #e0e0e0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 1px 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Wiki 宠物 */&lt;br /&gt;
.wiki-pet {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 50px;&lt;br /&gt;
    z-index: 9998;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    user-select: none;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet img {&lt;br /&gt;
    width: 100px;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
    image-rendering: auto;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:active {&lt;br /&gt;
    transform: scale(0.95);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.petting {&lt;br /&gt;
    animation: petBounce 0.6s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petBounce {&lt;br /&gt;
    0%, 100% { transform: scale(1); }&lt;br /&gt;
    30% { transform: scale(1.15) translateY(-10px); }&lt;br /&gt;
    50% { transform: scale(0.95) translateY(0); }&lt;br /&gt;
    70% { transform: scale(1.05) translateY(-5px); }&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.attacking {&lt;br /&gt;
    animation: petAttack 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petAttack {&lt;br /&gt;
    0% { transform: scale(1) translateX(0); }&lt;br /&gt;
    50% { transform: scale(1.1) translateX(-30px); }&lt;br /&gt;
    100% { transform: scale(1) translateX(0); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度面板 - 宠物上方，有间隔 */&lt;br /&gt;
.pet-affection {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
    background: rgba(0,0,0,0.7);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 3px 8px;&lt;br /&gt;
    border-radius: 10px;&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-affection {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 提示文字 - 好感度面板上方，紧贴无间隔 */&lt;br /&gt;
.pet-tooltip {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 28px;&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 6px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-tooltip {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度飘出 */&lt;br /&gt;
.pet-heart {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
    animation: floatUp 1.5s ease-out forwards;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
}&lt;br /&gt;
@keyframes floatUp {&lt;br /&gt;
    0% { opacity: 1; transform: translateY(0) scale(1); }&lt;br /&gt;
    100% { opacity: 0; transform: translateY(-60px) scale(1.5); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 升级特效 */&lt;br /&gt;
.wiki-pet.level-up {&lt;br /&gt;
    animation: levelUpGlow 0.8s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes levelUpGlow {&lt;br /&gt;
    0%, 100% { filter: drop-shadow(0 0 5px gold); }&lt;br /&gt;
    50% { filter: drop-shadow(0 0 20px gold) brightness(1.3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 宠物切换按钮 */&lt;br /&gt;
.pet-switch-btn {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: -5px;&lt;br /&gt;
    right: -5px;&lt;br /&gt;
    width: 24px;&lt;br /&gt;
    height: 24px;&lt;br /&gt;
    background: rgba(0,0,0,0.6);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: 1px solid rgba(255,255,255,0.3);&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    display: none;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 22px;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.pet-switch-btn:hover {&lt;br /&gt;
    transform: scale(1.2);&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-switch-btn,&lt;br /&gt;
.wiki-pet.touching .pet-switch-btn {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 阅读位置记忆开关 */&lt;br /&gt;
.readposition-switch {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    padding: 12px 0;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-text {&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-desc {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.card-counter {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    transition: box-shadow 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card:hover {&lt;br /&gt;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
}&lt;br /&gt;
/* 页面淡入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageFadeIn 0.4s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@keyframes pageFadeIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(8px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 页面进入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageIn 0.6s ease-out;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pageIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(60px) scale(0.9);&lt;br /&gt;
        filter: blur(10px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0) scale(1);&lt;br /&gt;
        filter: blur(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 卡通体 */&lt;br /&gt;
.font-cartoon {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡通斜体 */&lt;br /&gt;
.font-cartoon-italic {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
    font-style: italic !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手写体 */&lt;br /&gt;
.font-handwrite {&lt;br /&gt;
    font-family: &#039;STXingkai&#039;, &#039;华文行楷&#039;, &#039;STKaiti&#039;, &#039;楷体&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 方正剪纸 */&lt;br /&gt;
.font-fzjianzhi {&lt;br /&gt;
    font-family: &#039;FZJianZhi&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-huapop {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/a/a4/%E6%96%B9%E6%AD%A3%E5%8D%A1%E9%80%9A%E7%AE%80%E4%BD%93.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzkatong {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/5/58/Fzcq.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzcq {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
/* 卡片整体点击：让图片链接充满整个卡片 */&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    position: relative; /* 关键！让子元素绝对定位相对于卡片 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    display: block;&lt;br /&gt;
    z-index: 1; /* 覆盖在卡片内容之上 */&lt;br /&gt;
    /* 隐藏多余的图片边框/背景，但保留点击区域 */&lt;br /&gt;
    background: transparent !important;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a img {&lt;br /&gt;
    /* 保证图片仍然正常显示，但点击区域由 a 决定 */&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: -1; /* 将图片置于链接下层，避免遮挡内容 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-name {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: 2; /* 名字显示在链接之上，但仍然可点击 */&lt;br /&gt;
    pointer-events: none; /* 让点击穿透到链接层 */&lt;br /&gt;
}&lt;br /&gt;
.citizen-page-info:contains(&amp;quot;citizen-page-info-viewcount&amp;quot;) {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 用户子页面锁定状态 */&lt;br /&gt;
.user-subpage-locked {&lt;br /&gt;
    -webkit-user-modify: read-only;&lt;br /&gt;
}&lt;br /&gt;
.user-subpage-locked input,&lt;br /&gt;
.user-subpage-locked textarea,&lt;br /&gt;
.user-subpage-locked button[type=&amp;quot;submit&amp;quot;] {&lt;br /&gt;
    pointer-events: none !important;&lt;br /&gt;
    opacity: 0.6 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15415</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15415"/>
		<updated>2026-07-31T09:10:17Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户子页面保护 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
        var isSubpage = pageTitle.indexOf(&#039;/&#039;) !== -1;&lt;br /&gt;
&lt;br /&gt;
        // 如果是子页面，且当前用户不是页面所有者也不是管理员&lt;br /&gt;
        if (isSubpage) {&lt;br /&gt;
            var pageOwner = pageTitle.split(&#039;/&#039;)[0];&lt;br /&gt;
            var isAdmin = $.inArray(&#039;sysop&#039;, mw.config.get(&#039;wgUserGroups&#039;)) !== -1;&lt;br /&gt;
            var isOwner = currentUser === pageOwner;&lt;br /&gt;
&lt;br /&gt;
            if (!isOwner &amp;amp;&amp;amp; !isAdmin) {&lt;br /&gt;
                // 隐藏编辑按钮&lt;br /&gt;
                $(&#039;#ca-edit, #ca-ve-edit, .mw-editsection, #ca-talk, #ca-addsection&#039;).remove();&lt;br /&gt;
&lt;br /&gt;
                // 如果是编辑页面，重定向回查看页面&lt;br /&gt;
                if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
                    alert(&#039;⚠️ 你只能编辑自己的用户子页面！&#039;);&lt;br /&gt;
                    window.location.href = mw.util.getUrl(pageTitle);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 在页面顶部显示提示&lt;br /&gt;
                if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
                    var $warning = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        style: &#039;background:#fff3e0;border:1px solid #FF9800;padding:8px 15px;border-radius:8px;margin:10px 0;font-size:13px;color:#e65100;&#039;,&lt;br /&gt;
                        text: &#039;🔒 这是 &#039; + pageOwner + &#039; 的个人子页面，仅本人和管理员可编辑。&#039;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).prepend($warning);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 锁定页面交互&lt;br /&gt;
                $(&#039;body&#039;).addClass(&#039;user-subpage-locked&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15414</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15414"/>
		<updated>2026-07-31T08:57:52Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15413</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15413"/>
		<updated>2026-07-31T08:51:39Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
$(window).on(&#039;load&#039;, function() {&lt;br /&gt;
    var lastHeight = document.body.scrollHeight;&lt;br /&gt;
&lt;br /&gt;
    // 立即回顶一次&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
&lt;br /&gt;
    // 监听高度变化，变化了就是有东西加载撑开了页面&lt;br /&gt;
    var heightCheck = setInterval(function() {&lt;br /&gt;
        var currentHeight = document.body.scrollHeight;&lt;br /&gt;
        if (currentHeight !== lastHeight) {&lt;br /&gt;
            lastHeight = currentHeight;&lt;br /&gt;
            window.scrollTo(0, 0);&lt;br /&gt;
        }&lt;br /&gt;
    }, 200);&lt;br /&gt;
&lt;br /&gt;
    // 10 秒后停止监听&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        clearInterval(heightCheck);&lt;br /&gt;
    }, 10000);&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15410</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15410"/>
		<updated>2026-07-31T08:49:43Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
$(window).on(&#039;load&#039;, function() {&lt;br /&gt;
    var count = 0;&lt;br /&gt;
    var topTimer = setInterval(function() {&lt;br /&gt;
        window.scrollTo(0, 0);&lt;br /&gt;
        count++;&lt;br /&gt;
        if (count &amp;gt; 30) clearInterval(topTimer);&lt;br /&gt;
    }, 100);&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15408</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15408"/>
		<updated>2026-07-31T08:47:23Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
$(window).on(&#039;load&#039;, function() {&lt;br /&gt;
    if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        var topTimer = setInterval(function() {&lt;br /&gt;
            window.scrollTo(0, 0);&lt;br /&gt;
            count++;&lt;br /&gt;
            if (count &amp;gt; 30) clearInterval(topTimer);&lt;br /&gt;
        }, 100);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15404</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15404"/>
		<updated>2026-07-31T08:41:51Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
$(window).on(&#039;load&#039;, function() {&lt;br /&gt;
    // 只在没有阅读记忆的情况下才拉回顶部&lt;br /&gt;
    if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
        var topTimer = setInterval(function() {&lt;br /&gt;
            if (window.scrollY &amp;gt; 0) {&lt;br /&gt;
                window.scrollTo(0, 0);&lt;br /&gt;
            } else {&lt;br /&gt;
                clearInterval(topTimer);&lt;br /&gt;
            }&lt;br /&gt;
        }, 100);&lt;br /&gt;
&lt;br /&gt;
        // 安全超时 3 秒后停止&lt;br /&gt;
        setTimeout(function() {&lt;br /&gt;
            clearInterval(topTimer);&lt;br /&gt;
        }, 3000);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        // 保存位置（开关开启且滚动超过 100px 才存）&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var top = window.scrollY;&lt;br /&gt;
            if (top &amp;lt; 100) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                data[mw.config.get(&#039;wgPageName&#039;)] = top;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 恢复位置（开关开启且缓存中有当前页面的位置）&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                var top = data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                if (typeof top === &#039;number&#039; &amp;amp;&amp;amp; top &amp;gt; 0) {&lt;br /&gt;
                    window.scrollTo({ top: top, behavior: &#039;instant&#039; });&lt;br /&gt;
                }&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 插入开关到外观设置&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    // 关闭时清除当前页缓存&lt;br /&gt;
                    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                    delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 离开时保存&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, savePosition);&lt;br /&gt;
        setInterval(savePosition, 5000);&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复（放在 load 事件，等页面渲染完）&lt;br /&gt;
        $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
            setTimeout(restorePosition, 200);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 监听外观面板&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                insertSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertSwitch();&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15400</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15400"/>
		<updated>2026-07-31T08:35:02Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
document.documentElement.style.scrollBehavior = &#039;auto&#039;;&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        // 保存位置（开关开启且滚动超过 100px 才存）&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var top = window.scrollY;&lt;br /&gt;
            if (top &amp;lt; 100) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                data[mw.config.get(&#039;wgPageName&#039;)] = top;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 恢复位置（开关开启且缓存中有当前页面的位置）&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                var top = data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                if (typeof top === &#039;number&#039; &amp;amp;&amp;amp; top &amp;gt; 0) {&lt;br /&gt;
                    window.scrollTo({ top: top, behavior: &#039;instant&#039; });&lt;br /&gt;
                }&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 插入开关到外观设置&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    // 关闭时清除当前页缓存&lt;br /&gt;
                    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                    delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 离开时保存&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, savePosition);&lt;br /&gt;
        setInterval(savePosition, 5000);&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复（放在 load 事件，等页面渲染完）&lt;br /&gt;
        $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
            setTimeout(restorePosition, 200);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 监听外观面板&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                insertSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertSwitch();&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15397</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15397"/>
		<updated>2026-07-31T08:32:34Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        // 保存当前位置&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var top = window.scrollY || window.pageYOffset || 0;&lt;br /&gt;
            if (top &amp;lt; 50) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                data[mw.config.get(&#039;wgPageName&#039;)] = top;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 尝试恢复位置（仅当开关打开）&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) {&lt;br /&gt;
                // 开关关：删掉当前页缓存，防止任何意外恢复&lt;br /&gt;
                try {&lt;br /&gt;
                    var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                    delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                } catch(e) {}&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 开关开：恢复上次记录的位置&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                var pos = data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                if (typeof pos === &#039;number&#039; &amp;amp;&amp;amp; pos &amp;gt; 0) {&lt;br /&gt;
                    $(function() {&lt;br /&gt;
                        setTimeout(function() {&lt;br /&gt;
                            window.scrollTo({ top: pos, behavior: &#039;instant&#039; });&lt;br /&gt;
                        }, 100);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 添加外观开关&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    // 关闭时立刻清掉当前页的缓存&lt;br /&gt;
                    try {&lt;br /&gt;
                        var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                        localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                    } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 离开页面时保存&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, savePosition);&lt;br /&gt;
        setInterval(savePosition, 5000);&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时处理&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        // 监听外观面板&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                insertSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertSwitch();&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15396</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15396"/>
		<updated>2026-07-31T08:32:14Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 彻底禁止页面加载期间的自动滚动&lt;br /&gt;
var blockScrollUntilLoaded = true;&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    setTimeout(function() { blockScrollUntilLoaded = false; }, 800);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
var originalScrollTo = window.scrollTo;&lt;br /&gt;
window.scrollTo = function() {&lt;br /&gt;
    if (blockScrollUntilLoaded) return;&lt;br /&gt;
    originalScrollTo.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var originalScrollBy = window.scrollBy;&lt;br /&gt;
window.scrollBy = function() {&lt;br /&gt;
    if (blockScrollUntilLoaded) return;&lt;br /&gt;
    originalScrollBy.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var originalJqScrollTop = $.fn.scrollTop;&lt;br /&gt;
$.fn.scrollTop = function(val) {&lt;br /&gt;
    if (blockScrollUntilLoaded &amp;amp;&amp;amp; val !== undefined) return this;&lt;br /&gt;
    return originalJqScrollTop.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
    // ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
        var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleHeader() {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
            headerVisible = !headerVisible;&lt;br /&gt;
            localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (headerVisible) {&lt;br /&gt;
                $header.show();&lt;br /&gt;
            } else {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            showToast(headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showToast(msg) {&lt;br /&gt;
            var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                    padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                    fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                    opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
                },&lt;br /&gt;
                text: msg&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;body&#039;).append($toast);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
            setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                toggleHeader();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(function() {&lt;br /&gt;
            if (!headerVisible) {&lt;br /&gt;
                var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
                if ($header.length) {&lt;br /&gt;
                    $header.hide();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        // 保存当前位置&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var top = window.scrollY || window.pageYOffset || 0;&lt;br /&gt;
            if (top &amp;lt; 50) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                data[mw.config.get(&#039;wgPageName&#039;)] = top;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 尝试恢复位置（仅当开关打开）&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) {&lt;br /&gt;
                // 开关关：删掉当前页缓存，防止任何意外恢复&lt;br /&gt;
                try {&lt;br /&gt;
                    var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                    delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                } catch(e) {}&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 开关开：恢复上次记录的位置&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                var pos = data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                if (typeof pos === &#039;number&#039; &amp;amp;&amp;amp; pos &amp;gt; 0) {&lt;br /&gt;
                    $(function() {&lt;br /&gt;
                        setTimeout(function() {&lt;br /&gt;
                            window.scrollTo({ top: pos, behavior: &#039;instant&#039; });&lt;br /&gt;
                        }, 100);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 添加外观开关&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    // 关闭时立刻清掉当前页的缓存&lt;br /&gt;
                    try {&lt;br /&gt;
                        var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                        localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                    } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 离开页面时保存&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, savePosition);&lt;br /&gt;
        setInterval(savePosition, 5000);&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时处理&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        // 监听外观面板&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                insertSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertSwitch();&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15393</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15393"/>
		<updated>2026-07-31T08:29:43Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* 电脑端样式 */&lt;br /&gt;
.responsive-two-columns .left-col {&lt;br /&gt;
    width: 320px;&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns .right-col {&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
    padding-left: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 新增：响应式图片卡片样式 */&lt;br /&gt;
.gallery-card {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);  /* 一行两个，减去gap的一半 */&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card-small {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);&lt;br /&gt;
    max-width: 150px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card img,&lt;br /&gt;
.gallery-card-small img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.image-overlay {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 30px;&lt;br /&gt;
    left: 10px;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    color: white;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.flex-gallery {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: flex-start;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    align-items: flex-start;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 手机端响应式（768px以下） === */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    /* 两栏布局变单栏 */&lt;br /&gt;
    .responsive-two-columns,&lt;br /&gt;
    .responsive-two-columns tbody,&lt;br /&gt;
    .responsive-two-columns tr,&lt;br /&gt;
    .responsive-two-columns td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns .right-col {&lt;br /&gt;
        padding-left: 0;&lt;br /&gt;
        margin-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns img {&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* 画廊卡片保持一行两个 */&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: calc(50% - 5px);&lt;br /&gt;
        max-width: none;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* PVZ导航：改为Flex布局，一行三个 */&lt;br /&gt;
    .pvz-navigation {&lt;br /&gt;
        float: none;&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table {&lt;br /&gt;
        display: flex;&lt;br /&gt;
        flex-wrap: wrap;&lt;br /&gt;
        justify-content: center;&lt;br /&gt;
        gap: 5px;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tbody {&lt;br /&gt;
        display: contents;  /* 关键！让tbody不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tr {&lt;br /&gt;
        display: contents;  /* 关键！让tr不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        flex: 0 0 calc(33.33% - 5px);  /* 固定宽度一行三个 */&lt;br /&gt;
        width: auto !important;&lt;br /&gt;
        padding: 4px;&lt;br /&gt;
        box-sizing: border-box;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td img {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
        max-width: 120px;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-title {&lt;br /&gt;
        font-size: 1.2em;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 超小屏幕（宽度小于480px）时改为一行一个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 只有带链接且不在card/轮播内的图片才有悬停放大效果 */&lt;br /&gt;
a img {&lt;br /&gt;
    transition: transform 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a img:hover {&lt;br /&gt;
    transform: scale(1.08);&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 精确排除card模板和轮播图 - 不使用慢速选择器 */&lt;br /&gt;
.card a img,&lt;br /&gt;
.swiper a img,&lt;br /&gt;
.carousel a img,&lt;br /&gt;
.slider a img,&lt;br /&gt;
.owl-carousel a img,&lt;br /&gt;
.flexslider a img {&lt;br /&gt;
    transition: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.card a img:hover,&lt;br /&gt;
.swiper a img:hover,&lt;br /&gt;
.carousel a img:hover,&lt;br /&gt;
.slider a img:hover,&lt;br /&gt;
.owl-carousel a img:hover,&lt;br /&gt;
.flexslider a img:hover {&lt;br /&gt;
    transform: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 图片点击受击缩小 */&lt;br /&gt;
a img:active {&lt;br /&gt;
    transform: scale(0.92);&lt;br /&gt;
    transition: transform 0.1s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 表格响应式：电脑一行5个，手机自动换行 === */&lt;br /&gt;
&lt;br /&gt;
/* 电脑端：保持原样，固定5列 */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    width: auto;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    width: 20%;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手机端：表格变成弹性布局，自动换行 */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 5px;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid tbody,&lt;br /&gt;
  .responsive-fixed-grid tr {&lt;br /&gt;
    display: contents;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    display: block;&lt;br /&gt;
    flex: 0 1 auto;&lt;br /&gt;
    max-width: calc(33.33% - 6px);&lt;br /&gt;
    width: auto;&lt;br /&gt;
    padding: 3px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 更小屏幕：一行2个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    max-width: calc(50% - 5px);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    max-width: 750px;&lt;br /&gt;
}&lt;br /&gt;
/* 让所有图片都能响应式缩放 */&lt;br /&gt;
img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns {&lt;br /&gt;
    padding-left: 50px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        padding-left: 0 !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* === 首页表格左偏移（仅电脑端）=== */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        margin-left: -50px !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
/* 等级颜色 */&lt;br /&gt;
.bronze-user   { color: #CD7F32 !important; font-weight: bold; }&lt;br /&gt;
.silver-user   { color: #0000FF !important; font-weight: bold; }&lt;br /&gt;
.platinum-user { color: #EE82EE !important; font-weight: bold; }&lt;br /&gt;
.gold-user     { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
.rainbow-user  { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
&lt;br /&gt;
/* 状态圆点 */&lt;br /&gt;
.user-status-dot {&lt;br /&gt;
    display: inline-block; width: 8px; height: 8px;&lt;br /&gt;
    border-radius: 50%; margin-left: 4px; vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.status-online  { background-color: #4CAF50; }&lt;br /&gt;
.status-away    { background-color: #FF9800; }&lt;br /&gt;
.status-offline { background-color: #9E9E9E; }&lt;br /&gt;
&lt;br /&gt;
/* 师徒标签 */&lt;br /&gt;
.user-tag {&lt;br /&gt;
    display: inline-block; font-size: 0.75em; padding: 0px 4px;&lt;br /&gt;
    margin-left: 4px; border-radius: 3px; vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
.user-tag-mentor { background: #4CAF50; color: white; }&lt;br /&gt;
.user-tag-newbie { background: #FF9800; color: white; }&lt;br /&gt;
&lt;br /&gt;
/* 等级图标 */&lt;br /&gt;
.user-level-icons {&lt;br /&gt;
    margin-left: 2px; font-size: 0.9em; vertical-align: middle;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡片筛选隐藏 */&lt;br /&gt;
.pvzhe-card.hidden-card { display: none; }&lt;br /&gt;
&lt;br /&gt;
/* 编辑数昵称标签 */&lt;br /&gt;
.user-title-tag {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    font-size: 0.75em;&lt;br /&gt;
    padding: 1px 5px;&lt;br /&gt;
    margin-left: 4px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    background: #f0f0f0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 版本更新公告弹窗样式 */&lt;br /&gt;
.update-notice-content {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.update-version {&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #2c3e50;&lt;br /&gt;
    margin-bottom: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
.update-date {&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    margin-bottom: 15px;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul li {&lt;br /&gt;
    padding: 6px 0;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 返回顶部按钮 */&lt;br /&gt;
#back-to-top {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 40px;&lt;br /&gt;
    right: 30px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 45px;&lt;br /&gt;
    height: 45px;&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: none;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
    box-shadow: 0 2px 10px rgba(0,0,0,0.3);&lt;br /&gt;
    transition: opacity 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
#back-to-top:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
    transform: scale(1.1);&lt;br /&gt;
}&lt;br /&gt;
/* 私信系统样式 */&lt;br /&gt;
.msg-badge {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 20px;&lt;br /&gt;
    background: #f44336;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 20px;&lt;br /&gt;
    height: 20px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 20px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 100001;&lt;br /&gt;
    display: none;&lt;br /&gt;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);&lt;br /&gt;
    animation: msgPulse 2s infinite;&lt;br /&gt;
}&lt;br /&gt;
@keyframes msgPulse {&lt;br /&gt;
    0%, 100% { box-shadow: 0 2px 6px rgba(0,0,0,0.3); }&lt;br /&gt;
    50% { box-shadow: 0 2px 16px rgba(244,67,54,0.6); }&lt;br /&gt;
}&lt;br /&gt;
.msg-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.msg-box {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.msg-item {&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    padding: 10px 0;&lt;br /&gt;
}&lt;br /&gt;
.msg-sender {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.msg-time {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
}&lt;br /&gt;
.msg-text {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions button {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    padding: 2px 8px;&lt;br /&gt;
    margin-right: 5px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    background: #f9f9f9;&lt;br /&gt;
}&lt;br /&gt;
.msg-item.unread {&lt;br /&gt;
    background: #fffde7;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 2px 10px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #4CAF50;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
}&lt;br /&gt;
.msg-textarea {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    resize: vertical;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    margin-top: 10px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
.msg-loading {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
/* 好友系统 */&lt;br /&gt;
.friend-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.friend-add-btn { background: #4CAF50; }&lt;br /&gt;
.friend-add-btn:hover { background: #45a049; }&lt;br /&gt;
.friend-added-btn { background: #2196F3; }&lt;br /&gt;
.friend-added-btn:hover { background: #1e88e5; }&lt;br /&gt;
.friend-pending-btn { background: #FF9800; cursor: not-allowed; }&lt;br /&gt;
.friend-accept-btn { background: #4CAF50; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; margin-right: 5px; }&lt;br /&gt;
.friend-reject-btn { background: #f44336; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; }&lt;br /&gt;
.friend-list-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    margin: 4px 8px 4px 0;&lt;br /&gt;
    padding: 4px 10px;&lt;br /&gt;
    background: #f5f5f5;&lt;br /&gt;
    border-radius: 16px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item a { text-decoration: none; }&lt;br /&gt;
.friend-list-item .friend-remove {&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item .friend-remove:hover { color: #f44336; }&lt;br /&gt;
.friend-request-item {&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
}&lt;br /&gt;
.friend-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0; left: 0;&lt;br /&gt;
    width: 100%; height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.friend-dialog {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 450px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.friend-count {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #e0e0e0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 1px 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Wiki 宠物 */&lt;br /&gt;
.wiki-pet {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 50px;&lt;br /&gt;
    z-index: 9998;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    user-select: none;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet img {&lt;br /&gt;
    width: 100px;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
    image-rendering: auto;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:active {&lt;br /&gt;
    transform: scale(0.95);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.petting {&lt;br /&gt;
    animation: petBounce 0.6s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petBounce {&lt;br /&gt;
    0%, 100% { transform: scale(1); }&lt;br /&gt;
    30% { transform: scale(1.15) translateY(-10px); }&lt;br /&gt;
    50% { transform: scale(0.95) translateY(0); }&lt;br /&gt;
    70% { transform: scale(1.05) translateY(-5px); }&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.attacking {&lt;br /&gt;
    animation: petAttack 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petAttack {&lt;br /&gt;
    0% { transform: scale(1) translateX(0); }&lt;br /&gt;
    50% { transform: scale(1.1) translateX(-30px); }&lt;br /&gt;
    100% { transform: scale(1) translateX(0); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度面板 - 宠物上方，有间隔 */&lt;br /&gt;
.pet-affection {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
    background: rgba(0,0,0,0.7);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 3px 8px;&lt;br /&gt;
    border-radius: 10px;&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-affection {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 提示文字 - 好感度面板上方，紧贴无间隔 */&lt;br /&gt;
.pet-tooltip {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 28px;&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 6px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-tooltip {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度飘出 */&lt;br /&gt;
.pet-heart {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
    animation: floatUp 1.5s ease-out forwards;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
}&lt;br /&gt;
@keyframes floatUp {&lt;br /&gt;
    0% { opacity: 1; transform: translateY(0) scale(1); }&lt;br /&gt;
    100% { opacity: 0; transform: translateY(-60px) scale(1.5); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 升级特效 */&lt;br /&gt;
.wiki-pet.level-up {&lt;br /&gt;
    animation: levelUpGlow 0.8s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes levelUpGlow {&lt;br /&gt;
    0%, 100% { filter: drop-shadow(0 0 5px gold); }&lt;br /&gt;
    50% { filter: drop-shadow(0 0 20px gold) brightness(1.3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 宠物切换按钮 */&lt;br /&gt;
.pet-switch-btn {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: -5px;&lt;br /&gt;
    right: -5px;&lt;br /&gt;
    width: 24px;&lt;br /&gt;
    height: 24px;&lt;br /&gt;
    background: rgba(0,0,0,0.6);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: 1px solid rgba(255,255,255,0.3);&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    display: none;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 22px;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.pet-switch-btn:hover {&lt;br /&gt;
    transform: scale(1.2);&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-switch-btn,&lt;br /&gt;
.wiki-pet.touching .pet-switch-btn {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 阅读位置记忆开关 */&lt;br /&gt;
.readposition-switch {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    padding: 12px 0;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-text {&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-desc {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.card-counter {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    transition: box-shadow 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card:hover {&lt;br /&gt;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
}&lt;br /&gt;
/* 页面淡入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageFadeIn 0.4s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@keyframes pageFadeIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(8px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 页面进入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageIn 0.6s ease-out;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pageIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(60px) scale(0.9);&lt;br /&gt;
        filter: blur(10px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0) scale(1);&lt;br /&gt;
        filter: blur(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 卡通体 */&lt;br /&gt;
.font-cartoon {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡通斜体 */&lt;br /&gt;
.font-cartoon-italic {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
    font-style: italic !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手写体 */&lt;br /&gt;
.font-handwrite {&lt;br /&gt;
    font-family: &#039;STXingkai&#039;, &#039;华文行楷&#039;, &#039;STKaiti&#039;, &#039;楷体&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 方正剪纸 */&lt;br /&gt;
.font-fzjianzhi {&lt;br /&gt;
    font-family: &#039;FZJianZhi&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-huapop {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/a/a4/%E6%96%B9%E6%AD%A3%E5%8D%A1%E9%80%9A%E7%AE%80%E4%BD%93.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzkatong {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/5/58/Fzcq.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzcq {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
/* 卡片整体点击：让图片链接充满整个卡片 */&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    position: relative; /* 关键！让子元素绝对定位相对于卡片 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    display: block;&lt;br /&gt;
    z-index: 1; /* 覆盖在卡片内容之上 */&lt;br /&gt;
    /* 隐藏多余的图片边框/背景，但保留点击区域 */&lt;br /&gt;
    background: transparent !important;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a img {&lt;br /&gt;
    /* 保证图片仍然正常显示，但点击区域由 a 决定 */&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: -1; /* 将图片置于链接下层，避免遮挡内容 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-name {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: 2; /* 名字显示在链接之上，但仍然可点击 */&lt;br /&gt;
    pointer-events: none; /* 让点击穿透到链接层 */&lt;br /&gt;
}&lt;br /&gt;
.citizen-page-info:contains(&amp;quot;citizen-page-info-viewcount&amp;quot;) {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15392</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15392"/>
		<updated>2026-07-31T08:28:49Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;body {&lt;br /&gt;
    overflow-anchor: none;&lt;br /&gt;
    min-height: 100vh;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 电脑端样式 */&lt;br /&gt;
.responsive-two-columns .left-col {&lt;br /&gt;
    width: 320px;&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns .right-col {&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
    padding-left: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 新增：响应式图片卡片样式 */&lt;br /&gt;
.gallery-card {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);  /* 一行两个，减去gap的一半 */&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card-small {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);&lt;br /&gt;
    max-width: 150px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card img,&lt;br /&gt;
.gallery-card-small img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.image-overlay {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 30px;&lt;br /&gt;
    left: 10px;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    color: white;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.flex-gallery {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: flex-start;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    align-items: flex-start;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 手机端响应式（768px以下） === */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    /* 两栏布局变单栏 */&lt;br /&gt;
    .responsive-two-columns,&lt;br /&gt;
    .responsive-two-columns tbody,&lt;br /&gt;
    .responsive-two-columns tr,&lt;br /&gt;
    .responsive-two-columns td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns .right-col {&lt;br /&gt;
        padding-left: 0;&lt;br /&gt;
        margin-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns img {&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* 画廊卡片保持一行两个 */&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: calc(50% - 5px);&lt;br /&gt;
        max-width: none;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* PVZ导航：改为Flex布局，一行三个 */&lt;br /&gt;
    .pvz-navigation {&lt;br /&gt;
        float: none;&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table {&lt;br /&gt;
        display: flex;&lt;br /&gt;
        flex-wrap: wrap;&lt;br /&gt;
        justify-content: center;&lt;br /&gt;
        gap: 5px;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tbody {&lt;br /&gt;
        display: contents;  /* 关键！让tbody不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tr {&lt;br /&gt;
        display: contents;  /* 关键！让tr不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        flex: 0 0 calc(33.33% - 5px);  /* 固定宽度一行三个 */&lt;br /&gt;
        width: auto !important;&lt;br /&gt;
        padding: 4px;&lt;br /&gt;
        box-sizing: border-box;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td img {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
        max-width: 120px;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-title {&lt;br /&gt;
        font-size: 1.2em;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 超小屏幕（宽度小于480px）时改为一行一个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 只有带链接且不在card/轮播内的图片才有悬停放大效果 */&lt;br /&gt;
a img {&lt;br /&gt;
    transition: transform 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a img:hover {&lt;br /&gt;
    transform: scale(1.08);&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 精确排除card模板和轮播图 - 不使用慢速选择器 */&lt;br /&gt;
.card a img,&lt;br /&gt;
.swiper a img,&lt;br /&gt;
.carousel a img,&lt;br /&gt;
.slider a img,&lt;br /&gt;
.owl-carousel a img,&lt;br /&gt;
.flexslider a img {&lt;br /&gt;
    transition: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.card a img:hover,&lt;br /&gt;
.swiper a img:hover,&lt;br /&gt;
.carousel a img:hover,&lt;br /&gt;
.slider a img:hover,&lt;br /&gt;
.owl-carousel a img:hover,&lt;br /&gt;
.flexslider a img:hover {&lt;br /&gt;
    transform: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 图片点击受击缩小 */&lt;br /&gt;
a img:active {&lt;br /&gt;
    transform: scale(0.92);&lt;br /&gt;
    transition: transform 0.1s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 表格响应式：电脑一行5个，手机自动换行 === */&lt;br /&gt;
&lt;br /&gt;
/* 电脑端：保持原样，固定5列 */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    width: auto;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    width: 20%;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手机端：表格变成弹性布局，自动换行 */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 5px;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid tbody,&lt;br /&gt;
  .responsive-fixed-grid tr {&lt;br /&gt;
    display: contents;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    display: block;&lt;br /&gt;
    flex: 0 1 auto;&lt;br /&gt;
    max-width: calc(33.33% - 6px);&lt;br /&gt;
    width: auto;&lt;br /&gt;
    padding: 3px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 更小屏幕：一行2个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    max-width: calc(50% - 5px);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    max-width: 750px;&lt;br /&gt;
}&lt;br /&gt;
/* 让所有图片都能响应式缩放 */&lt;br /&gt;
img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns {&lt;br /&gt;
    padding-left: 50px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        padding-left: 0 !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* === 首页表格左偏移（仅电脑端）=== */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        margin-left: -50px !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
/* 等级颜色 */&lt;br /&gt;
.bronze-user   { color: #CD7F32 !important; font-weight: bold; }&lt;br /&gt;
.silver-user   { color: #0000FF !important; font-weight: bold; }&lt;br /&gt;
.platinum-user { color: #EE82EE !important; font-weight: bold; }&lt;br /&gt;
.gold-user     { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
.rainbow-user  { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
&lt;br /&gt;
/* 状态圆点 */&lt;br /&gt;
.user-status-dot {&lt;br /&gt;
    display: inline-block; width: 8px; height: 8px;&lt;br /&gt;
    border-radius: 50%; margin-left: 4px; vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.status-online  { background-color: #4CAF50; }&lt;br /&gt;
.status-away    { background-color: #FF9800; }&lt;br /&gt;
.status-offline { background-color: #9E9E9E; }&lt;br /&gt;
&lt;br /&gt;
/* 师徒标签 */&lt;br /&gt;
.user-tag {&lt;br /&gt;
    display: inline-block; font-size: 0.75em; padding: 0px 4px;&lt;br /&gt;
    margin-left: 4px; border-radius: 3px; vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
.user-tag-mentor { background: #4CAF50; color: white; }&lt;br /&gt;
.user-tag-newbie { background: #FF9800; color: white; }&lt;br /&gt;
&lt;br /&gt;
/* 等级图标 */&lt;br /&gt;
.user-level-icons {&lt;br /&gt;
    margin-left: 2px; font-size: 0.9em; vertical-align: middle;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡片筛选隐藏 */&lt;br /&gt;
.pvzhe-card.hidden-card { display: none; }&lt;br /&gt;
&lt;br /&gt;
/* 编辑数昵称标签 */&lt;br /&gt;
.user-title-tag {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    font-size: 0.75em;&lt;br /&gt;
    padding: 1px 5px;&lt;br /&gt;
    margin-left: 4px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    background: #f0f0f0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 版本更新公告弹窗样式 */&lt;br /&gt;
.update-notice-content {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.update-version {&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #2c3e50;&lt;br /&gt;
    margin-bottom: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
.update-date {&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    margin-bottom: 15px;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul li {&lt;br /&gt;
    padding: 6px 0;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 返回顶部按钮 */&lt;br /&gt;
#back-to-top {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 40px;&lt;br /&gt;
    right: 30px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 45px;&lt;br /&gt;
    height: 45px;&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: none;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
    box-shadow: 0 2px 10px rgba(0,0,0,0.3);&lt;br /&gt;
    transition: opacity 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
#back-to-top:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
    transform: scale(1.1);&lt;br /&gt;
}&lt;br /&gt;
/* 私信系统样式 */&lt;br /&gt;
.msg-badge {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 20px;&lt;br /&gt;
    background: #f44336;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 20px;&lt;br /&gt;
    height: 20px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 20px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 100001;&lt;br /&gt;
    display: none;&lt;br /&gt;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);&lt;br /&gt;
    animation: msgPulse 2s infinite;&lt;br /&gt;
}&lt;br /&gt;
@keyframes msgPulse {&lt;br /&gt;
    0%, 100% { box-shadow: 0 2px 6px rgba(0,0,0,0.3); }&lt;br /&gt;
    50% { box-shadow: 0 2px 16px rgba(244,67,54,0.6); }&lt;br /&gt;
}&lt;br /&gt;
.msg-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.msg-box {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.msg-item {&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    padding: 10px 0;&lt;br /&gt;
}&lt;br /&gt;
.msg-sender {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.msg-time {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
}&lt;br /&gt;
.msg-text {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions button {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    padding: 2px 8px;&lt;br /&gt;
    margin-right: 5px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    background: #f9f9f9;&lt;br /&gt;
}&lt;br /&gt;
.msg-item.unread {&lt;br /&gt;
    background: #fffde7;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 2px 10px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #4CAF50;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
}&lt;br /&gt;
.msg-textarea {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    resize: vertical;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    margin-top: 10px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
.msg-loading {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
/* 好友系统 */&lt;br /&gt;
.friend-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.friend-add-btn { background: #4CAF50; }&lt;br /&gt;
.friend-add-btn:hover { background: #45a049; }&lt;br /&gt;
.friend-added-btn { background: #2196F3; }&lt;br /&gt;
.friend-added-btn:hover { background: #1e88e5; }&lt;br /&gt;
.friend-pending-btn { background: #FF9800; cursor: not-allowed; }&lt;br /&gt;
.friend-accept-btn { background: #4CAF50; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; margin-right: 5px; }&lt;br /&gt;
.friend-reject-btn { background: #f44336; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; }&lt;br /&gt;
.friend-list-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    margin: 4px 8px 4px 0;&lt;br /&gt;
    padding: 4px 10px;&lt;br /&gt;
    background: #f5f5f5;&lt;br /&gt;
    border-radius: 16px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item a { text-decoration: none; }&lt;br /&gt;
.friend-list-item .friend-remove {&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item .friend-remove:hover { color: #f44336; }&lt;br /&gt;
.friend-request-item {&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
}&lt;br /&gt;
.friend-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0; left: 0;&lt;br /&gt;
    width: 100%; height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.friend-dialog {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 450px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.friend-count {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #e0e0e0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 1px 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Wiki 宠物 */&lt;br /&gt;
.wiki-pet {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 50px;&lt;br /&gt;
    z-index: 9998;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    user-select: none;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet img {&lt;br /&gt;
    width: 100px;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
    image-rendering: auto;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:active {&lt;br /&gt;
    transform: scale(0.95);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.petting {&lt;br /&gt;
    animation: petBounce 0.6s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petBounce {&lt;br /&gt;
    0%, 100% { transform: scale(1); }&lt;br /&gt;
    30% { transform: scale(1.15) translateY(-10px); }&lt;br /&gt;
    50% { transform: scale(0.95) translateY(0); }&lt;br /&gt;
    70% { transform: scale(1.05) translateY(-5px); }&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.attacking {&lt;br /&gt;
    animation: petAttack 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petAttack {&lt;br /&gt;
    0% { transform: scale(1) translateX(0); }&lt;br /&gt;
    50% { transform: scale(1.1) translateX(-30px); }&lt;br /&gt;
    100% { transform: scale(1) translateX(0); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度面板 - 宠物上方，有间隔 */&lt;br /&gt;
.pet-affection {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
    background: rgba(0,0,0,0.7);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 3px 8px;&lt;br /&gt;
    border-radius: 10px;&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-affection {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 提示文字 - 好感度面板上方，紧贴无间隔 */&lt;br /&gt;
.pet-tooltip {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 28px;&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 6px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-tooltip {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度飘出 */&lt;br /&gt;
.pet-heart {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
    animation: floatUp 1.5s ease-out forwards;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
}&lt;br /&gt;
@keyframes floatUp {&lt;br /&gt;
    0% { opacity: 1; transform: translateY(0) scale(1); }&lt;br /&gt;
    100% { opacity: 0; transform: translateY(-60px) scale(1.5); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 升级特效 */&lt;br /&gt;
.wiki-pet.level-up {&lt;br /&gt;
    animation: levelUpGlow 0.8s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes levelUpGlow {&lt;br /&gt;
    0%, 100% { filter: drop-shadow(0 0 5px gold); }&lt;br /&gt;
    50% { filter: drop-shadow(0 0 20px gold) brightness(1.3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 宠物切换按钮 */&lt;br /&gt;
.pet-switch-btn {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: -5px;&lt;br /&gt;
    right: -5px;&lt;br /&gt;
    width: 24px;&lt;br /&gt;
    height: 24px;&lt;br /&gt;
    background: rgba(0,0,0,0.6);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: 1px solid rgba(255,255,255,0.3);&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    display: none;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 22px;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.pet-switch-btn:hover {&lt;br /&gt;
    transform: scale(1.2);&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-switch-btn,&lt;br /&gt;
.wiki-pet.touching .pet-switch-btn {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 阅读位置记忆开关 */&lt;br /&gt;
.readposition-switch {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    padding: 12px 0;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-text {&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-desc {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.card-counter {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    transition: box-shadow 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card:hover {&lt;br /&gt;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
}&lt;br /&gt;
/* 页面淡入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageFadeIn 0.4s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@keyframes pageFadeIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(8px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 页面进入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageIn 0.6s ease-out;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pageIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(60px) scale(0.9);&lt;br /&gt;
        filter: blur(10px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0) scale(1);&lt;br /&gt;
        filter: blur(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 卡通体 */&lt;br /&gt;
.font-cartoon {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡通斜体 */&lt;br /&gt;
.font-cartoon-italic {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
    font-style: italic !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手写体 */&lt;br /&gt;
.font-handwrite {&lt;br /&gt;
    font-family: &#039;STXingkai&#039;, &#039;华文行楷&#039;, &#039;STKaiti&#039;, &#039;楷体&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 方正剪纸 */&lt;br /&gt;
.font-fzjianzhi {&lt;br /&gt;
    font-family: &#039;FZJianZhi&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-huapop {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/a/a4/%E6%96%B9%E6%AD%A3%E5%8D%A1%E9%80%9A%E7%AE%80%E4%BD%93.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzkatong {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/5/58/Fzcq.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzcq {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
/* 卡片整体点击：让图片链接充满整个卡片 */&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    position: relative; /* 关键！让子元素绝对定位相对于卡片 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    display: block;&lt;br /&gt;
    z-index: 1; /* 覆盖在卡片内容之上 */&lt;br /&gt;
    /* 隐藏多余的图片边框/背景，但保留点击区域 */&lt;br /&gt;
    background: transparent !important;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a img {&lt;br /&gt;
    /* 保证图片仍然正常显示，但点击区域由 a 决定 */&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: -1; /* 将图片置于链接下层，避免遮挡内容 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-name {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: 2; /* 名字显示在链接之上，但仍然可点击 */&lt;br /&gt;
    pointer-events: none; /* 让点击穿透到链接层 */&lt;br /&gt;
}&lt;br /&gt;
.citizen-page-info:contains(&amp;quot;citizen-page-info-viewcount&amp;quot;) {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15391</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15391"/>
		<updated>2026-07-31T08:28:21Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 彻底禁止页面加载期间的自动滚动&lt;br /&gt;
var blockScrollUntilLoaded = true;&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    setTimeout(function() { blockScrollUntilLoaded = false; }, 800);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
var originalScrollTo = window.scrollTo;&lt;br /&gt;
window.scrollTo = function() {&lt;br /&gt;
    if (blockScrollUntilLoaded) return;&lt;br /&gt;
    originalScrollTo.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var originalScrollBy = window.scrollBy;&lt;br /&gt;
window.scrollBy = function() {&lt;br /&gt;
    if (blockScrollUntilLoaded) return;&lt;br /&gt;
    originalScrollBy.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var originalJqScrollTop = $.fn.scrollTop;&lt;br /&gt;
$.fn.scrollTop = function(val) {&lt;br /&gt;
    if (blockScrollUntilLoaded &amp;amp;&amp;amp; val !== undefined) return this;&lt;br /&gt;
    return originalJqScrollTop.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        // 保存当前位置&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var top = window.scrollY || window.pageYOffset || 0;&lt;br /&gt;
            if (top &amp;lt; 50) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                data[mw.config.get(&#039;wgPageName&#039;)] = top;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 尝试恢复位置（仅当开关打开）&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) {&lt;br /&gt;
                // 开关关：删掉当前页缓存，防止任何意外恢复&lt;br /&gt;
                try {&lt;br /&gt;
                    var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                    delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                } catch(e) {}&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 开关开：恢复上次记录的位置&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                var pos = data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                if (typeof pos === &#039;number&#039; &amp;amp;&amp;amp; pos &amp;gt; 0) {&lt;br /&gt;
                    $(function() {&lt;br /&gt;
                        setTimeout(function() {&lt;br /&gt;
                            window.scrollTo({ top: pos, behavior: &#039;instant&#039; });&lt;br /&gt;
                        }, 100);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 添加外观开关&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    // 关闭时立刻清掉当前页的缓存&lt;br /&gt;
                    try {&lt;br /&gt;
                        var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                        localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                    } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 离开页面时保存&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, savePosition);&lt;br /&gt;
        setInterval(savePosition, 5000);&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时处理&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        // 监听外观面板&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                insertSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertSwitch();&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15389</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15389"/>
		<updated>2026-07-31T08:27:17Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 强制浏览器忘记所有滚动位置&lt;br /&gt;
window.addEventListener(&#039;beforeunload&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 页面加载后立刻回顶&lt;br /&gt;
window.scrollTo(0, 0);&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
    setTimeout(function() { window.scrollTo(0, 0); }, 100);&lt;br /&gt;
    setTimeout(function() { window.scrollTo(0, 0); }, 500);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 禁止浏览器恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        // 保存当前位置&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var top = window.scrollY || window.pageYOffset || 0;&lt;br /&gt;
            if (top &amp;lt; 50) return;&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                data[mw.config.get(&#039;wgPageName&#039;)] = top;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 尝试恢复位置（仅当开关打开）&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) {&lt;br /&gt;
                // 开关关：删掉当前页缓存，防止任何意外恢复&lt;br /&gt;
                try {&lt;br /&gt;
                    var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                    delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                } catch(e) {}&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 开关开：恢复上次记录的位置&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                var pos = data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                if (typeof pos === &#039;number&#039; &amp;amp;&amp;amp; pos &amp;gt; 0) {&lt;br /&gt;
                    $(function() {&lt;br /&gt;
                        setTimeout(function() {&lt;br /&gt;
                            window.scrollTo({ top: pos, behavior: &#039;instant&#039; });&lt;br /&gt;
                        }, 100);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            } catch(e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 添加外观开关&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    // 关闭时立刻清掉当前页的缓存&lt;br /&gt;
                    try {&lt;br /&gt;
                        var data = JSON.parse(localStorage.getItem(positionKey)) || {};&lt;br /&gt;
                        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
                        localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
                    } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 离开页面时保存&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, savePosition);&lt;br /&gt;
        setInterval(savePosition, 5000);&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时处理&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        // 监听外观面板&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                insertSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertSwitch();&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15388</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15388"/>
		<updated>2026-07-31T08:24:57Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 强制浏览器忘记所有滚动位置&lt;br /&gt;
window.addEventListener(&#039;beforeunload&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 页面加载后立刻回顶&lt;br /&gt;
window.scrollTo(0, 0);&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
    setTimeout(function() { window.scrollTo(0, 0); }, 100);&lt;br /&gt;
    setTimeout(function() { window.scrollTo(0, 0); }, 500);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 禁止浏览器恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
function restorePosition() {&lt;br /&gt;
    // 开关关闭 → 清除当前页缓存，不恢复&lt;br /&gt;
    if (!enabled) {&lt;br /&gt;
        var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
        localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    // 开关开启 → 恢复位置&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    if (data[currentPage]) {&lt;br /&gt;
        $(function() {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                window.scrollTo({ top: data[currentPage], behavior: &#039;instant&#039; });&lt;br /&gt;
            }, 100);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function savePosition() {&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var scrollTop = $(window).scrollTop();&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    data[currentPage] = scrollTop;&lt;br /&gt;
    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15385</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15385"/>
		<updated>2026-07-31T08:23:04Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 禁止浏览器恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
&lt;br /&gt;
// 阅读记忆关闭时清除缓存并回顶&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
        var data = JSON.parse(localStorage.getItem(&#039;mw_readposition_data&#039;) || &#039;{}&#039;);&lt;br /&gt;
        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
        localStorage.setItem(&#039;mw_readposition_data&#039;, JSON.stringify(data));&lt;br /&gt;
        window.scrollTo(0, 0);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
function restorePosition() {&lt;br /&gt;
    // 开关关闭 → 清除当前页缓存，不恢复&lt;br /&gt;
    if (!enabled) {&lt;br /&gt;
        var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
        localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    // 开关开启 → 恢复位置&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    if (data[currentPage]) {&lt;br /&gt;
        $(function() {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                window.scrollTo({ top: data[currentPage], behavior: &#039;instant&#039; });&lt;br /&gt;
            }, 100);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function savePosition() {&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var scrollTop = $(window).scrollTop();&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    data[currentPage] = scrollTop;&lt;br /&gt;
    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15382</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15382"/>
		<updated>2026-07-31T08:21:16Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 禁止浏览器恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
&lt;br /&gt;
// 阅读记忆关闭时清除缓存并回顶&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
        var data = JSON.parse(localStorage.getItem(&#039;mw_readposition_data&#039;) || &#039;{}&#039;);&lt;br /&gt;
        delete data[mw.config.get(&#039;wgPageName&#039;)];&lt;br /&gt;
        localStorage.setItem(&#039;mw_readposition_data&#039;, JSON.stringify(data));&lt;br /&gt;
        window.scrollTo(0, 0);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
function restorePosition() {&lt;br /&gt;
    if (!enabled) {&lt;br /&gt;
        // 开关关闭时，清除所有缓存，不恢复&lt;br /&gt;
        localStorage.removeItem(positionKey);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    if (data[currentPage]) {&lt;br /&gt;
        var scrollTarget = data[currentPage];&lt;br /&gt;
        $(function() {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                window.scrollTo({ top: scrollTarget, behavior: &#039;instant&#039; });&lt;br /&gt;
            }, 500);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function savePosition() {&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var scrollTop = $(window).scrollTop();&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    data[currentPage] = scrollTop;&lt;br /&gt;
    localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15381</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15381"/>
		<updated>2026-07-31T08:17:13Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
function restorePosition() {&lt;br /&gt;
    if (!enabled) {&lt;br /&gt;
        // 开关关闭时，清除所有缓存，不恢复&lt;br /&gt;
        localStorage.removeItem(positionKey);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    if (data[currentPage]) {&lt;br /&gt;
        var scrollTarget = data[currentPage];&lt;br /&gt;
        $(function() {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                window.scrollTo({ top: scrollTarget, behavior: &#039;instant&#039; });&lt;br /&gt;
            }, 500);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15377</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15377"/>
		<updated>2026-07-31T08:12:09Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;body {&lt;br /&gt;
    animation: swooshIn 0.35s ease-out;&lt;br /&gt;
    overflow-anchor: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 电脑端样式 */&lt;br /&gt;
.responsive-two-columns .left-col {&lt;br /&gt;
    width: 320px;&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns .right-col {&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
    padding-left: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 新增：响应式图片卡片样式 */&lt;br /&gt;
.gallery-card {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);  /* 一行两个，减去gap的一半 */&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card-small {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);&lt;br /&gt;
    max-width: 150px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card img,&lt;br /&gt;
.gallery-card-small img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.image-overlay {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 30px;&lt;br /&gt;
    left: 10px;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    color: white;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.flex-gallery {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: flex-start;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    align-items: flex-start;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 手机端响应式（768px以下） === */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    /* 两栏布局变单栏 */&lt;br /&gt;
    .responsive-two-columns,&lt;br /&gt;
    .responsive-two-columns tbody,&lt;br /&gt;
    .responsive-two-columns tr,&lt;br /&gt;
    .responsive-two-columns td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns .right-col {&lt;br /&gt;
        padding-left: 0;&lt;br /&gt;
        margin-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns img {&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* 画廊卡片保持一行两个 */&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: calc(50% - 5px);&lt;br /&gt;
        max-width: none;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* PVZ导航：改为Flex布局，一行三个 */&lt;br /&gt;
    .pvz-navigation {&lt;br /&gt;
        float: none;&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table {&lt;br /&gt;
        display: flex;&lt;br /&gt;
        flex-wrap: wrap;&lt;br /&gt;
        justify-content: center;&lt;br /&gt;
        gap: 5px;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tbody {&lt;br /&gt;
        display: contents;  /* 关键！让tbody不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tr {&lt;br /&gt;
        display: contents;  /* 关键！让tr不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        flex: 0 0 calc(33.33% - 5px);  /* 固定宽度一行三个 */&lt;br /&gt;
        width: auto !important;&lt;br /&gt;
        padding: 4px;&lt;br /&gt;
        box-sizing: border-box;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td img {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
        max-width: 120px;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-title {&lt;br /&gt;
        font-size: 1.2em;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 超小屏幕（宽度小于480px）时改为一行一个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 只有带链接且不在card/轮播内的图片才有悬停放大效果 */&lt;br /&gt;
a img {&lt;br /&gt;
    transition: transform 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a img:hover {&lt;br /&gt;
    transform: scale(1.08);&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 精确排除card模板和轮播图 - 不使用慢速选择器 */&lt;br /&gt;
.card a img,&lt;br /&gt;
.swiper a img,&lt;br /&gt;
.carousel a img,&lt;br /&gt;
.slider a img,&lt;br /&gt;
.owl-carousel a img,&lt;br /&gt;
.flexslider a img {&lt;br /&gt;
    transition: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.card a img:hover,&lt;br /&gt;
.swiper a img:hover,&lt;br /&gt;
.carousel a img:hover,&lt;br /&gt;
.slider a img:hover,&lt;br /&gt;
.owl-carousel a img:hover,&lt;br /&gt;
.flexslider a img:hover {&lt;br /&gt;
    transform: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 图片点击受击缩小 */&lt;br /&gt;
a img:active {&lt;br /&gt;
    transform: scale(0.92);&lt;br /&gt;
    transition: transform 0.1s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 表格响应式：电脑一行5个，手机自动换行 === */&lt;br /&gt;
&lt;br /&gt;
/* 电脑端：保持原样，固定5列 */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    width: auto;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    width: 20%;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手机端：表格变成弹性布局，自动换行 */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 5px;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid tbody,&lt;br /&gt;
  .responsive-fixed-grid tr {&lt;br /&gt;
    display: contents;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    display: block;&lt;br /&gt;
    flex: 0 1 auto;&lt;br /&gt;
    max-width: calc(33.33% - 6px);&lt;br /&gt;
    width: auto;&lt;br /&gt;
    padding: 3px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 更小屏幕：一行2个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    max-width: calc(50% - 5px);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    max-width: 750px;&lt;br /&gt;
}&lt;br /&gt;
/* 让所有图片都能响应式缩放 */&lt;br /&gt;
img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns {&lt;br /&gt;
    padding-left: 50px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        padding-left: 0 !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* === 首页表格左偏移（仅电脑端）=== */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        margin-left: -50px !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
/* 等级颜色 */&lt;br /&gt;
.bronze-user   { color: #CD7F32 !important; font-weight: bold; }&lt;br /&gt;
.silver-user   { color: #0000FF !important; font-weight: bold; }&lt;br /&gt;
.platinum-user { color: #EE82EE !important; font-weight: bold; }&lt;br /&gt;
.gold-user     { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
.rainbow-user  { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
&lt;br /&gt;
/* 状态圆点 */&lt;br /&gt;
.user-status-dot {&lt;br /&gt;
    display: inline-block; width: 8px; height: 8px;&lt;br /&gt;
    border-radius: 50%; margin-left: 4px; vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.status-online  { background-color: #4CAF50; }&lt;br /&gt;
.status-away    { background-color: #FF9800; }&lt;br /&gt;
.status-offline { background-color: #9E9E9E; }&lt;br /&gt;
&lt;br /&gt;
/* 师徒标签 */&lt;br /&gt;
.user-tag {&lt;br /&gt;
    display: inline-block; font-size: 0.75em; padding: 0px 4px;&lt;br /&gt;
    margin-left: 4px; border-radius: 3px; vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
.user-tag-mentor { background: #4CAF50; color: white; }&lt;br /&gt;
.user-tag-newbie { background: #FF9800; color: white; }&lt;br /&gt;
&lt;br /&gt;
/* 等级图标 */&lt;br /&gt;
.user-level-icons {&lt;br /&gt;
    margin-left: 2px; font-size: 0.9em; vertical-align: middle;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡片筛选隐藏 */&lt;br /&gt;
.pvzhe-card.hidden-card { display: none; }&lt;br /&gt;
&lt;br /&gt;
/* 编辑数昵称标签 */&lt;br /&gt;
.user-title-tag {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    font-size: 0.75em;&lt;br /&gt;
    padding: 1px 5px;&lt;br /&gt;
    margin-left: 4px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    background: #f0f0f0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 版本更新公告弹窗样式 */&lt;br /&gt;
.update-notice-content {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.update-version {&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #2c3e50;&lt;br /&gt;
    margin-bottom: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
.update-date {&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    margin-bottom: 15px;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul li {&lt;br /&gt;
    padding: 6px 0;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 返回顶部按钮 */&lt;br /&gt;
#back-to-top {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 40px;&lt;br /&gt;
    right: 30px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 45px;&lt;br /&gt;
    height: 45px;&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: none;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
    box-shadow: 0 2px 10px rgba(0,0,0,0.3);&lt;br /&gt;
    transition: opacity 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
#back-to-top:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
    transform: scale(1.1);&lt;br /&gt;
}&lt;br /&gt;
/* 私信系统样式 */&lt;br /&gt;
.msg-badge {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 20px;&lt;br /&gt;
    background: #f44336;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 20px;&lt;br /&gt;
    height: 20px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 20px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 100001;&lt;br /&gt;
    display: none;&lt;br /&gt;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);&lt;br /&gt;
    animation: msgPulse 2s infinite;&lt;br /&gt;
}&lt;br /&gt;
@keyframes msgPulse {&lt;br /&gt;
    0%, 100% { box-shadow: 0 2px 6px rgba(0,0,0,0.3); }&lt;br /&gt;
    50% { box-shadow: 0 2px 16px rgba(244,67,54,0.6); }&lt;br /&gt;
}&lt;br /&gt;
.msg-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.msg-box {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.msg-item {&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    padding: 10px 0;&lt;br /&gt;
}&lt;br /&gt;
.msg-sender {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.msg-time {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
}&lt;br /&gt;
.msg-text {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions button {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    padding: 2px 8px;&lt;br /&gt;
    margin-right: 5px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    background: #f9f9f9;&lt;br /&gt;
}&lt;br /&gt;
.msg-item.unread {&lt;br /&gt;
    background: #fffde7;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 2px 10px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #4CAF50;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
}&lt;br /&gt;
.msg-textarea {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    resize: vertical;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    margin-top: 10px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
.msg-loading {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
/* 好友系统 */&lt;br /&gt;
.friend-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.friend-add-btn { background: #4CAF50; }&lt;br /&gt;
.friend-add-btn:hover { background: #45a049; }&lt;br /&gt;
.friend-added-btn { background: #2196F3; }&lt;br /&gt;
.friend-added-btn:hover { background: #1e88e5; }&lt;br /&gt;
.friend-pending-btn { background: #FF9800; cursor: not-allowed; }&lt;br /&gt;
.friend-accept-btn { background: #4CAF50; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; margin-right: 5px; }&lt;br /&gt;
.friend-reject-btn { background: #f44336; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; }&lt;br /&gt;
.friend-list-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    margin: 4px 8px 4px 0;&lt;br /&gt;
    padding: 4px 10px;&lt;br /&gt;
    background: #f5f5f5;&lt;br /&gt;
    border-radius: 16px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item a { text-decoration: none; }&lt;br /&gt;
.friend-list-item .friend-remove {&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item .friend-remove:hover { color: #f44336; }&lt;br /&gt;
.friend-request-item {&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
}&lt;br /&gt;
.friend-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0; left: 0;&lt;br /&gt;
    width: 100%; height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.friend-dialog {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 450px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.friend-count {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #e0e0e0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 1px 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Wiki 宠物 */&lt;br /&gt;
.wiki-pet {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 50px;&lt;br /&gt;
    z-index: 9998;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    user-select: none;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet img {&lt;br /&gt;
    width: 100px;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
    image-rendering: auto;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:active {&lt;br /&gt;
    transform: scale(0.95);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.petting {&lt;br /&gt;
    animation: petBounce 0.6s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petBounce {&lt;br /&gt;
    0%, 100% { transform: scale(1); }&lt;br /&gt;
    30% { transform: scale(1.15) translateY(-10px); }&lt;br /&gt;
    50% { transform: scale(0.95) translateY(0); }&lt;br /&gt;
    70% { transform: scale(1.05) translateY(-5px); }&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.attacking {&lt;br /&gt;
    animation: petAttack 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petAttack {&lt;br /&gt;
    0% { transform: scale(1) translateX(0); }&lt;br /&gt;
    50% { transform: scale(1.1) translateX(-30px); }&lt;br /&gt;
    100% { transform: scale(1) translateX(0); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度面板 - 宠物上方，有间隔 */&lt;br /&gt;
.pet-affection {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
    background: rgba(0,0,0,0.7);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 3px 8px;&lt;br /&gt;
    border-radius: 10px;&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-affection {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 提示文字 - 好感度面板上方，紧贴无间隔 */&lt;br /&gt;
.pet-tooltip {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 28px;&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 6px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-tooltip {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度飘出 */&lt;br /&gt;
.pet-heart {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
    animation: floatUp 1.5s ease-out forwards;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
}&lt;br /&gt;
@keyframes floatUp {&lt;br /&gt;
    0% { opacity: 1; transform: translateY(0) scale(1); }&lt;br /&gt;
    100% { opacity: 0; transform: translateY(-60px) scale(1.5); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 升级特效 */&lt;br /&gt;
.wiki-pet.level-up {&lt;br /&gt;
    animation: levelUpGlow 0.8s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes levelUpGlow {&lt;br /&gt;
    0%, 100% { filter: drop-shadow(0 0 5px gold); }&lt;br /&gt;
    50% { filter: drop-shadow(0 0 20px gold) brightness(1.3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 宠物切换按钮 */&lt;br /&gt;
.pet-switch-btn {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: -5px;&lt;br /&gt;
    right: -5px;&lt;br /&gt;
    width: 24px;&lt;br /&gt;
    height: 24px;&lt;br /&gt;
    background: rgba(0,0,0,0.6);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: 1px solid rgba(255,255,255,0.3);&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    display: none;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 22px;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.pet-switch-btn:hover {&lt;br /&gt;
    transform: scale(1.2);&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-switch-btn,&lt;br /&gt;
.wiki-pet.touching .pet-switch-btn {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 阅读位置记忆开关 */&lt;br /&gt;
.readposition-switch {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    padding: 12px 0;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-text {&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-desc {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.card-counter {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    transition: box-shadow 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card:hover {&lt;br /&gt;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
}&lt;br /&gt;
/* 页面淡入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageFadeIn 0.4s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@keyframes pageFadeIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(8px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 页面进入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageIn 0.6s ease-out;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pageIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(60px) scale(0.9);&lt;br /&gt;
        filter: blur(10px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0) scale(1);&lt;br /&gt;
        filter: blur(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 卡通体 */&lt;br /&gt;
.font-cartoon {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡通斜体 */&lt;br /&gt;
.font-cartoon-italic {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
    font-style: italic !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手写体 */&lt;br /&gt;
.font-handwrite {&lt;br /&gt;
    font-family: &#039;STXingkai&#039;, &#039;华文行楷&#039;, &#039;STKaiti&#039;, &#039;楷体&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 方正剪纸 */&lt;br /&gt;
.font-fzjianzhi {&lt;br /&gt;
    font-family: &#039;FZJianZhi&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-huapop {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/a/a4/%E6%96%B9%E6%AD%A3%E5%8D%A1%E9%80%9A%E7%AE%80%E4%BD%93.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzkatong {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/5/58/Fzcq.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzcq {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
/* 卡片整体点击：让图片链接充满整个卡片 */&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    position: relative; /* 关键！让子元素绝对定位相对于卡片 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    display: block;&lt;br /&gt;
    z-index: 1; /* 覆盖在卡片内容之上 */&lt;br /&gt;
    /* 隐藏多余的图片边框/背景，但保留点击区域 */&lt;br /&gt;
    background: transparent !important;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a img {&lt;br /&gt;
    /* 保证图片仍然正常显示，但点击区域由 a 决定 */&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: -1; /* 将图片置于链接下层，避免遮挡内容 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-name {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: 2; /* 名字显示在链接之上，但仍然可点击 */&lt;br /&gt;
    pointer-events: none; /* 让点击穿透到链接层 */&lt;br /&gt;
}&lt;br /&gt;
.citizen-page-info:contains(&amp;quot;citizen-page-info-viewcount&amp;quot;) {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15375</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15375"/>
		<updated>2026-07-31T08:10:56Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
$(&#039;html, body&#039;).scrollTop(0);&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
function restorePosition() {&lt;br /&gt;
    if (!enabled) {&lt;br /&gt;
        // 开关关闭时，清除所有缓存，不恢复&lt;br /&gt;
        localStorage.removeItem(positionKey);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
    var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    if (data[currentPage]) {&lt;br /&gt;
        var scrollTarget = data[currentPage];&lt;br /&gt;
        $(function() {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                window.scrollTo({ top: scrollTarget, behavior: &#039;instant&#039; });&lt;br /&gt;
            }, 500);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15373</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15373"/>
		<updated>2026-07-31T08:07:39Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
$(&#039;html, body&#039;).scrollTop(0);&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15371</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15371"/>
		<updated>2026-07-31T08:05:27Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 离开页面前滚回顶部，让浏览器记住的位置是 0&lt;br /&gt;
window.addEventListener(&#039;beforeunload&#039;, function() {&lt;br /&gt;
    if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
        window.scrollTo(0, 0);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 禁止浏览器自身恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15369</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.css&amp;diff=15369"/>
		<updated>2026-07-31T08:02:21Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;html {&lt;br /&gt;
    scroll-behavior: auto !important;&lt;br /&gt;
    overflow-anchor: none !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 电脑端样式 */&lt;br /&gt;
.responsive-two-columns .left-col {&lt;br /&gt;
    width: 320px;&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns .right-col {&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
    padding-left: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 新增：响应式图片卡片样式 */&lt;br /&gt;
.gallery-card {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);  /* 一行两个，减去gap的一半 */&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card-small {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: calc(50% - 5px);&lt;br /&gt;
    max-width: 150px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-card img,&lt;br /&gt;
.gallery-card-small img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.image-overlay {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 30px;&lt;br /&gt;
    left: 10px;&lt;br /&gt;
    text-align: left;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    color: white;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.flex-gallery {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: flex-start;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    align-items: flex-start;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 手机端响应式（768px以下） === */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    /* 两栏布局变单栏 */&lt;br /&gt;
    .responsive-two-columns,&lt;br /&gt;
    .responsive-two-columns tbody,&lt;br /&gt;
    .responsive-two-columns tr,&lt;br /&gt;
    .responsive-two-columns td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns .right-col {&lt;br /&gt;
        padding-left: 0;&lt;br /&gt;
        margin-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .responsive-two-columns img {&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* 画廊卡片保持一行两个 */&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: calc(50% - 5px);&lt;br /&gt;
        max-width: none;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* PVZ导航：改为Flex布局，一行三个 */&lt;br /&gt;
    .pvz-navigation {&lt;br /&gt;
        float: none;&lt;br /&gt;
        max-width: 100%;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table {&lt;br /&gt;
        display: flex;&lt;br /&gt;
        flex-wrap: wrap;&lt;br /&gt;
        justify-content: center;&lt;br /&gt;
        gap: 5px;&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tbody {&lt;br /&gt;
        display: contents;  /* 关键！让tbody不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table tr {&lt;br /&gt;
        display: contents;  /* 关键！让tr不影响flex布局 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td {&lt;br /&gt;
        display: block;&lt;br /&gt;
        flex: 0 0 calc(33.33% - 5px);  /* 固定宽度一行三个 */&lt;br /&gt;
        width: auto !important;&lt;br /&gt;
        padding: 4px;&lt;br /&gt;
        box-sizing: border-box;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-table td img {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
        max-width: 120px;&lt;br /&gt;
        height: auto;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    .pvz-navigation .nav-title {&lt;br /&gt;
        font-size: 1.2em;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 超小屏幕（宽度小于480px）时改为一行一个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
    .gallery-card,&lt;br /&gt;
    .gallery-card-small {&lt;br /&gt;
        width: 100%;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 只有带链接且不在card/轮播内的图片才有悬停放大效果 */&lt;br /&gt;
a img {&lt;br /&gt;
    transition: transform 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a img:hover {&lt;br /&gt;
    transform: scale(1.08);&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 精确排除card模板和轮播图 - 不使用慢速选择器 */&lt;br /&gt;
.card a img,&lt;br /&gt;
.swiper a img,&lt;br /&gt;
.carousel a img,&lt;br /&gt;
.slider a img,&lt;br /&gt;
.owl-carousel a img,&lt;br /&gt;
.flexslider a img {&lt;br /&gt;
    transition: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.card a img:hover,&lt;br /&gt;
.swiper a img:hover,&lt;br /&gt;
.carousel a img:hover,&lt;br /&gt;
.slider a img:hover,&lt;br /&gt;
.owl-carousel a img:hover,&lt;br /&gt;
.flexslider a img:hover {&lt;br /&gt;
    transform: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 图片点击受击缩小 */&lt;br /&gt;
a img:active {&lt;br /&gt;
    transform: scale(0.92);&lt;br /&gt;
    transition: transform 0.1s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* === 表格响应式：电脑一行5个，手机自动换行 === */&lt;br /&gt;
&lt;br /&gt;
/* 电脑端：保持原样，固定5列 */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    width: auto;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    table-layout: fixed;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    width: 20%;&lt;br /&gt;
    padding: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手机端：表格变成弹性布局，自动换行 */&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
  .responsive-fixed-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 5px;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid tbody,&lt;br /&gt;
  .responsive-fixed-grid tr {&lt;br /&gt;
    display: contents;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    display: block;&lt;br /&gt;
    flex: 0 1 auto;&lt;br /&gt;
    max-width: calc(33.33% - 6px);&lt;br /&gt;
    width: auto;&lt;br /&gt;
    padding: 3px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  .responsive-fixed-grid td img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 更小屏幕：一行2个 */&lt;br /&gt;
@media screen and (max-width: 480px) {&lt;br /&gt;
  .responsive-fixed-grid td {&lt;br /&gt;
    max-width: calc(50% - 5px);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    max-width: 750px;&lt;br /&gt;
}&lt;br /&gt;
/* 让所有图片都能响应式缩放 */&lt;br /&gt;
img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
.responsive-two-columns {&lt;br /&gt;
    padding-left: 50px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        padding-left: 0 !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* === 首页表格左偏移（仅电脑端）=== */&lt;br /&gt;
@media screen and (min-width: 769px) {&lt;br /&gt;
    .responsive-two-columns {&lt;br /&gt;
        margin-left: -50px !important;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.responsive-img img {&lt;br /&gt;
    max-width: 100%;&lt;br /&gt;
    height: auto;&lt;br /&gt;
}&lt;br /&gt;
/* 等级颜色 */&lt;br /&gt;
.bronze-user   { color: #CD7F32 !important; font-weight: bold; }&lt;br /&gt;
.silver-user   { color: #0000FF !important; font-weight: bold; }&lt;br /&gt;
.platinum-user { color: #EE82EE !important; font-weight: bold; }&lt;br /&gt;
.gold-user     { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
.rainbow-user  { color: #FFD700 !important; font-weight: bold; }&lt;br /&gt;
&lt;br /&gt;
/* 状态圆点 */&lt;br /&gt;
.user-status-dot {&lt;br /&gt;
    display: inline-block; width: 8px; height: 8px;&lt;br /&gt;
    border-radius: 50%; margin-left: 4px; vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.status-online  { background-color: #4CAF50; }&lt;br /&gt;
.status-away    { background-color: #FF9800; }&lt;br /&gt;
.status-offline { background-color: #9E9E9E; }&lt;br /&gt;
&lt;br /&gt;
/* 师徒标签 */&lt;br /&gt;
.user-tag {&lt;br /&gt;
    display: inline-block; font-size: 0.75em; padding: 0px 4px;&lt;br /&gt;
    margin-left: 4px; border-radius: 3px; vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
.user-tag-mentor { background: #4CAF50; color: white; }&lt;br /&gt;
.user-tag-newbie { background: #FF9800; color: white; }&lt;br /&gt;
&lt;br /&gt;
/* 等级图标 */&lt;br /&gt;
.user-level-icons {&lt;br /&gt;
    margin-left: 2px; font-size: 0.9em; vertical-align: middle;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡片筛选隐藏 */&lt;br /&gt;
.pvzhe-card.hidden-card { display: none; }&lt;br /&gt;
&lt;br /&gt;
/* 编辑数昵称标签 */&lt;br /&gt;
.user-title-tag {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    font-size: 0.75em;&lt;br /&gt;
    padding: 1px 5px;&lt;br /&gt;
    margin-left: 4px;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    background: #f0f0f0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 版本更新公告弹窗样式 */&lt;br /&gt;
.update-notice-content {&lt;br /&gt;
    font-family: sans-serif;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.update-version {&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #2c3e50;&lt;br /&gt;
    margin-bottom: 5px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
.update-date {&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    margin-bottom: 15px;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
.update-notice-content ul li {&lt;br /&gt;
    padding: 6px 0;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 返回顶部按钮 */&lt;br /&gt;
#back-to-top {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 40px;&lt;br /&gt;
    right: 30px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 45px;&lt;br /&gt;
    height: 45px;&lt;br /&gt;
    font-size: 22px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: none;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
    box-shadow: 0 2px 10px rgba(0,0,0,0.3);&lt;br /&gt;
    transition: opacity 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
#back-to-top:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
    transform: scale(1.1);&lt;br /&gt;
}&lt;br /&gt;
/* 私信系统样式 */&lt;br /&gt;
.msg-badge {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 20px;&lt;br /&gt;
    background: #f44336;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    width: 20px;&lt;br /&gt;
    height: 20px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 20px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 100001;&lt;br /&gt;
    display: none;&lt;br /&gt;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);&lt;br /&gt;
    animation: msgPulse 2s infinite;&lt;br /&gt;
}&lt;br /&gt;
@keyframes msgPulse {&lt;br /&gt;
    0%, 100% { box-shadow: 0 2px 6px rgba(0,0,0,0.3); }&lt;br /&gt;
    50% { box-shadow: 0 2px 16px rgba(244,67,54,0.6); }&lt;br /&gt;
}&lt;br /&gt;
.msg-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.msg-box {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 500px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.msg-item {&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    padding: 10px 0;&lt;br /&gt;
}&lt;br /&gt;
.msg-sender {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
.msg-time {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
}&lt;br /&gt;
.msg-text {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions {&lt;br /&gt;
    margin-top: 4px;&lt;br /&gt;
}&lt;br /&gt;
.msg-actions button {&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    padding: 2px 8px;&lt;br /&gt;
    margin-right: 5px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 3px;&lt;br /&gt;
    background: #f9f9f9;&lt;br /&gt;
}&lt;br /&gt;
.msg-item.unread {&lt;br /&gt;
    background: #fffde7;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 2px 10px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: 1px solid #4CAF50;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.msg-send-btn:hover {&lt;br /&gt;
    background: #45a049;&lt;br /&gt;
}&lt;br /&gt;
.msg-textarea {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border: 1px solid #ccc;&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    resize: vertical;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    margin-top: 10px;&lt;br /&gt;
    box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
.msg-loading {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
/* 好友系统 */&lt;br /&gt;
.friend-btn {&lt;br /&gt;
    margin-left: 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 4px;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
.friend-add-btn { background: #4CAF50; }&lt;br /&gt;
.friend-add-btn:hover { background: #45a049; }&lt;br /&gt;
.friend-added-btn { background: #2196F3; }&lt;br /&gt;
.friend-added-btn:hover { background: #1e88e5; }&lt;br /&gt;
.friend-pending-btn { background: #FF9800; cursor: not-allowed; }&lt;br /&gt;
.friend-accept-btn { background: #4CAF50; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; margin-right: 5px; }&lt;br /&gt;
.friend-reject-btn { background: #f44336; font-size: 11px; padding: 2px 8px; cursor: pointer; border: none; color: #fff; border-radius: 3px; }&lt;br /&gt;
.friend-list-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    margin: 4px 8px 4px 0;&lt;br /&gt;
    padding: 4px 10px;&lt;br /&gt;
    background: #f5f5f5;&lt;br /&gt;
    border-radius: 16px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item a { text-decoration: none; }&lt;br /&gt;
.friend-list-item .friend-remove {&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
    color: #999;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
.friend-list-item .friend-remove:hover { color: #f44336; }&lt;br /&gt;
.friend-request-item {&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border-bottom: 1px solid #eee;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
}&lt;br /&gt;
.friend-overlay {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    top: 0; left: 0;&lt;br /&gt;
    width: 100%; height: 100%;&lt;br /&gt;
    background: rgba(0,0,0,0.5);&lt;br /&gt;
    z-index: 100000;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
.friend-dialog {&lt;br /&gt;
    background: #fff;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 25px;&lt;br /&gt;
    max-width: 450px;&lt;br /&gt;
    width: 90%;&lt;br /&gt;
    max-height: 70vh;&lt;br /&gt;
    overflow-y: auto;&lt;br /&gt;
    box-shadow: 0 8px 30px rgba(0,0,0,0.4);&lt;br /&gt;
}&lt;br /&gt;
.friend-count {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #e0e0e0;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    padding: 1px 8px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    margin-left: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Wiki 宠物 */&lt;br /&gt;
.wiki-pet {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    bottom: 20px;&lt;br /&gt;
    left: 50px;&lt;br /&gt;
    z-index: 9998;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    user-select: none;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet img {&lt;br /&gt;
    width: 100px;&lt;br /&gt;
    height: auto;&lt;br /&gt;
    display: block;&lt;br /&gt;
    image-rendering: auto;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:active {&lt;br /&gt;
    transform: scale(0.95);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.petting {&lt;br /&gt;
    animation: petBounce 0.6s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petBounce {&lt;br /&gt;
    0%, 100% { transform: scale(1); }&lt;br /&gt;
    30% { transform: scale(1.15) translateY(-10px); }&lt;br /&gt;
    50% { transform: scale(0.95) translateY(0); }&lt;br /&gt;
    70% { transform: scale(1.05) translateY(-5px); }&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet.attacking {&lt;br /&gt;
    animation: petAttack 0.3s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes petAttack {&lt;br /&gt;
    0% { transform: scale(1) translateX(0); }&lt;br /&gt;
    50% { transform: scale(1.1) translateX(-30px); }&lt;br /&gt;
    100% { transform: scale(1) translateX(0); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度面板 - 宠物上方，有间隔 */&lt;br /&gt;
.pet-affection {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
    background: rgba(0,0,0,0.7);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 3px 8px;&lt;br /&gt;
    border-radius: 10px;&lt;br /&gt;
    font-size: 11px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-affection {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 提示文字 - 好感度面板上方，紧贴无间隔 */&lt;br /&gt;
.pet-tooltip {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 100%;&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    transform: translateX(-50%);&lt;br /&gt;
    margin-bottom: 28px;&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 6px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.3s;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-tooltip {&lt;br /&gt;
    opacity: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 好感度飘出 */&lt;br /&gt;
.pet-heart {&lt;br /&gt;
    position: fixed;&lt;br /&gt;
    pointer-events: none;&lt;br /&gt;
    animation: floatUp 1.5s ease-out forwards;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    z-index: 9999;&lt;br /&gt;
}&lt;br /&gt;
@keyframes floatUp {&lt;br /&gt;
    0% { opacity: 1; transform: translateY(0) scale(1); }&lt;br /&gt;
    100% { opacity: 0; transform: translateY(-60px) scale(1.5); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 升级特效 */&lt;br /&gt;
.wiki-pet.level-up {&lt;br /&gt;
    animation: levelUpGlow 0.8s ease;&lt;br /&gt;
}&lt;br /&gt;
@keyframes levelUpGlow {&lt;br /&gt;
    0%, 100% { filter: drop-shadow(0 0 5px gold); }&lt;br /&gt;
    50% { filter: drop-shadow(0 0 20px gold) brightness(1.3); }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 宠物切换按钮 */&lt;br /&gt;
.pet-switch-btn {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: -5px;&lt;br /&gt;
    right: -5px;&lt;br /&gt;
    width: 24px;&lt;br /&gt;
    height: 24px;&lt;br /&gt;
    background: rgba(0,0,0,0.6);&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    border: 1px solid rgba(255,255,255,0.3);&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
    display: none;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    line-height: 22px;&lt;br /&gt;
    transition: transform 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.pet-switch-btn:hover {&lt;br /&gt;
    transform: scale(1.2);&lt;br /&gt;
    background: rgba(0,0,0,0.8);&lt;br /&gt;
}&lt;br /&gt;
.wiki-pet:hover .pet-switch-btn,&lt;br /&gt;
.wiki-pet.touching .pet-switch-btn {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 阅读位置记忆开关 */&lt;br /&gt;
.readposition-switch {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 10px;&lt;br /&gt;
    padding: 12px 0;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-text {&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    font-weight: 500;&lt;br /&gt;
}&lt;br /&gt;
.readposition-switch .readposition-label-desc {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (max-width: 768px) {&lt;br /&gt;
    .wiki-pet {&lt;br /&gt;
        bottom: 60px;&lt;br /&gt;
        left: 10px;&lt;br /&gt;
    }&lt;br /&gt;
    .wiki-pet img {&lt;br /&gt;
        width: 70px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
.card-counter {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    background: #4CAF50;&lt;br /&gt;
    color: #fff;&lt;br /&gt;
    padding: 4px 12px;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    margin-bottom: 8px;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    transition: box-shadow 0.3s, transform 0.3s;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card:hover {&lt;br /&gt;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
}&lt;br /&gt;
/* 页面淡入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageFadeIn 0.4s ease;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@keyframes pageFadeIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(8px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 页面进入动画 */&lt;br /&gt;
body {&lt;br /&gt;
    animation: pageIn 0.6s ease-out;&lt;br /&gt;
}&lt;br /&gt;
@keyframes pageIn {&lt;br /&gt;
    0% {&lt;br /&gt;
        opacity: 0;&lt;br /&gt;
        transform: translateY(60px) scale(0.9);&lt;br /&gt;
        filter: blur(10px);&lt;br /&gt;
    }&lt;br /&gt;
    100% {&lt;br /&gt;
        opacity: 1;&lt;br /&gt;
        transform: translateY(0) scale(1);&lt;br /&gt;
        filter: blur(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/* 卡通体 */&lt;br /&gt;
.font-cartoon {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 卡通斜体 */&lt;br /&gt;
.font-cartoon-italic {&lt;br /&gt;
    font-family: &#039;Comic Sans MS&#039;, &#039;Chalkboard SE&#039;, cursive, sans-serif !important;&lt;br /&gt;
    font-style: italic !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 手写体 */&lt;br /&gt;
.font-handwrite {&lt;br /&gt;
    font-family: &#039;STXingkai&#039;, &#039;华文行楷&#039;, &#039;STKaiti&#039;, &#039;楷体&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* 方正剪纸 */&lt;br /&gt;
.font-fzjianzhi {&lt;br /&gt;
    font-family: &#039;FZJianZhi&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-huapop {&lt;br /&gt;
    font-family: &#039;Huakang POP2 W9&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/a/a4/%E6%96%B9%E6%AD%A3%E5%8D%A1%E9%80%9A%E7%AE%80%E4%BD%93.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzkatong {&lt;br /&gt;
    font-family: &#039;FZKaTong&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, cursive, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;;&lt;br /&gt;
    src: url(&#039;https://new.pvzhe.wiki/images/5/58/Fzcq.woff2&#039;) format(&#039;woff2&#039;);&lt;br /&gt;
    font-weight: normal;&lt;br /&gt;
    font-style: normal;&lt;br /&gt;
    font-display: swap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.font-fzcq {&lt;br /&gt;
    font-family: &#039;FZCQ&#039;, &#039;PingFang SC&#039;, &#039;Microsoft YaHei&#039;, sans-serif !important;&lt;br /&gt;
}&lt;br /&gt;
/* 卡片整体点击：让图片链接充满整个卡片 */&lt;br /&gt;
.pvzhe-card {&lt;br /&gt;
    position: relative; /* 关键！让子元素绝对定位相对于卡片 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    top: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    display: block;&lt;br /&gt;
    z-index: 1; /* 覆盖在卡片内容之上 */&lt;br /&gt;
    /* 隐藏多余的图片边框/背景，但保留点击区域 */&lt;br /&gt;
    background: transparent !important;&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-image a img {&lt;br /&gt;
    /* 保证图片仍然正常显示，但点击区域由 a 决定 */&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: -1; /* 将图片置于链接下层，避免遮挡内容 */&lt;br /&gt;
}&lt;br /&gt;
.pvzhe-card-name {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    z-index: 2; /* 名字显示在链接之上，但仍然可点击 */&lt;br /&gt;
    pointer-events: none; /* 让点击穿透到链接层 */&lt;br /&gt;
}&lt;br /&gt;
.citizen-page-info:contains(&amp;quot;citizen-page-info-viewcount&amp;quot;) {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #888;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15368</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15368"/>
		<updated>2026-07-31T08:00:07Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 1. 禁止浏览器自己恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// 2. 清除残余滚动缓存&lt;br /&gt;
window.addEventListener(&#039;beforeunload&#039;, function() {&lt;br /&gt;
    sessionStorage.removeItem(&#039;scrollPos&#039;);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 3. 连续强制回顶（只在没开记忆时）&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
        window.scrollTo(0, 0);&lt;br /&gt;
        setTimeout(function() { window.scrollTo(0, 0); }, 200);&lt;br /&gt;
        setTimeout(function() { window.scrollTo(0, 0); }, 600);&lt;br /&gt;
        setTimeout(function() { window.scrollTo(0, 0); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15367</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15367"/>
		<updated>2026-07-31T07:57:20Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 1. 禁止浏览器自身恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// 2. 页面完全加载后，如果阅读记忆没开，强制回顶&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    var lastHeight = document.body.scrollHeight;&lt;br /&gt;
    var stableCount = 0;&lt;br /&gt;
    var check = setInterval(function() {&lt;br /&gt;
        var currentHeight = document.body.scrollHeight;&lt;br /&gt;
        if (currentHeight === lastHeight) {&lt;br /&gt;
            stableCount++;&lt;br /&gt;
            if (stableCount &amp;gt;= 4) { // 连续 4 次不变 = 页面真正稳定&lt;br /&gt;
                if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
                    window.scrollTo(0, 0);&lt;br /&gt;
                }&lt;br /&gt;
                clearInterval(check);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            stableCount = 0;&lt;br /&gt;
            lastHeight = currentHeight;&lt;br /&gt;
        }&lt;br /&gt;
    }, 150);&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15366</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15366"/>
		<updated>2026-07-31T07:54:47Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 禁止所有非代码触发的滚动&lt;br /&gt;
var realScrollTo = window.scrollTo;&lt;br /&gt;
window.scrollTo = function(x, y) {&lt;br /&gt;
    // 只允许明确数字的滚动，拒绝事件对象&lt;br /&gt;
    if (typeof x === &#039;number&#039; &amp;amp;&amp;amp; typeof y === &#039;number&#039;) {&lt;br /&gt;
        realScrollTo.call(this, x, y);&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var realScroll = window.scroll;&lt;br /&gt;
window.scroll = function(x, y) {&lt;br /&gt;
    if (typeof x === &#039;number&#039; &amp;amp;&amp;amp; typeof y === &#039;number&#039;) {&lt;br /&gt;
        realScroll.call(this, x, y);&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15365</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15365"/>
		<updated>2026-07-31T07:47:12Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 禁止浏览器恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// 页面完全稳定后拉到顶部&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    var lastHeight = document.body.scrollHeight;&lt;br /&gt;
    var stableCount = 0;&lt;br /&gt;
    var check = setInterval(function() {&lt;br /&gt;
        var currentHeight = document.body.scrollHeight;&lt;br /&gt;
        if (currentHeight === lastHeight) {&lt;br /&gt;
            stableCount++;&lt;br /&gt;
            if (stableCount &amp;gt;= 3) {&lt;br /&gt;
                window.scrollTo(0, 0);&lt;br /&gt;
                clearInterval(check);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            stableCount = 0;&lt;br /&gt;
            lastHeight = currentHeight;&lt;br /&gt;
        }&lt;br /&gt;
    }, 200);&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15364</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15364"/>
		<updated>2026-07-31T07:44:51Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 禁止浏览器自动恢复滚动位置&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// 清除所有残留的滚动缓存&lt;br /&gt;
window.addEventListener(&#039;beforeunload&#039;, function() {&lt;br /&gt;
    sessionStorage.removeItem(&#039;scrollPos&#039;);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// 页面加载后强制回顶（只执行一次）&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    var checkCount = 0;&lt;br /&gt;
    var fixScroll = setInterval(function() {&lt;br /&gt;
        if (window.scrollY &amp;gt; 10) {&lt;br /&gt;
            window.scrollTo(0, 0);&lt;br /&gt;
        }&lt;br /&gt;
        checkCount++;&lt;br /&gt;
        if (checkCount &amp;gt; 20) clearInterval(fixScroll);&lt;br /&gt;
    }, 50);&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15361</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15361"/>
		<updated>2026-07-31T07:29:15Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 禁止浏览器自动恢复滚动&lt;br /&gt;
if (&#039;scrollRestoration&#039; in history) {&lt;br /&gt;
    history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
}&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15358</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15358"/>
		<updated>2026-07-31T07:26:37Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 只在阅读位置记忆关闭时，强制页面加载后在顶部&lt;br /&gt;
if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
    window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
        window.scrollTo(0, 0);&lt;br /&gt;
    });&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
            window.scrollTo(0, 0);&lt;br /&gt;
        }&lt;br /&gt;
    }, 100);&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        if (localStorage.getItem(&#039;mw_readposition_enabled&#039;) !== &#039;true&#039;) {&lt;br /&gt;
            window.scrollTo(0, 0);&lt;br /&gt;
        }&lt;br /&gt;
    }, 500);&lt;br /&gt;
}&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15355</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15355"/>
		<updated>2026-07-31T07:22:47Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 强制页面加载后在顶部&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
});&lt;br /&gt;
setTimeout(function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
}, 100);&lt;br /&gt;
setTimeout(function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
}, 500);&lt;br /&gt;
setTimeout(function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
}, 1000);&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var musicTimeKey = &#039;wiki_bgm_time&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function initMusic() {&lt;br /&gt;
            if (!bgmAudio) {&lt;br /&gt;
                bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                bgmAudio.loop = true;&lt;br /&gt;
                bgmAudio.volume = 0.3;&lt;br /&gt;
            }&lt;br /&gt;
            // 恢复上一次的播放进度&lt;br /&gt;
            var savedTime = parseFloat(sessionStorage.getItem(musicTimeKey)) || 0;&lt;br /&gt;
            if (savedTime &amp;gt; 0) {&lt;br /&gt;
                bgmAudio.currentTime = savedTime;&lt;br /&gt;
            }&lt;br /&gt;
            if (musicEnabled) {&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (musicEnabled) {&lt;br /&gt;
                    initMusic();&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (bgmAudio) {&lt;br /&gt;
                        sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
                        bgmAudio.pause();&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 页面加载时恢复&lt;br /&gt;
        if (musicEnabled) {&lt;br /&gt;
            $(function() {&lt;br /&gt;
                setTimeout(initMusic, 500);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 跳转前保存播放进度&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            if (bgmAudio &amp;amp;&amp;amp; !bgmAudio.paused) {&lt;br /&gt;
                sessionStorage.setItem(musicTimeKey, bgmAudio.currentTime);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15352</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15352"/>
		<updated>2026-07-31T07:18:09Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 强制页面加载后在顶部&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
});&lt;br /&gt;
setTimeout(function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
}, 100);&lt;br /&gt;
setTimeout(function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
}, 500);&lt;br /&gt;
setTimeout(function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
}, 1000);&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleMusic(musicEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function toggleMusic(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!bgmAudio) {&lt;br /&gt;
                    bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                    bgmAudio.loop = true;&lt;br /&gt;
                    bgmAudio.volume = 0.3;&lt;br /&gt;
                }&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                if (bgmAudio) {&lt;br /&gt;
                    bgmAudio.pause();&lt;br /&gt;
                    bgmAudio.currentTime = 0;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 默认关闭&lt;br /&gt;
        if (!musicEnabled) {&lt;br /&gt;
            $(&#039;#wiki-bgm&#039;).remove();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15351</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15351"/>
		<updated>2026-07-31T07:14:02Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// 强制页面加载时在顶部&lt;br /&gt;
window.addEventListener(&#039;load&#039;, function() {&lt;br /&gt;
    window.scrollTo(0, 0);&lt;br /&gt;
});&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleMusic(musicEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function toggleMusic(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!bgmAudio) {&lt;br /&gt;
                    bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                    bgmAudio.loop = true;&lt;br /&gt;
                    bgmAudio.volume = 0.3;&lt;br /&gt;
                }&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                if (bgmAudio) {&lt;br /&gt;
                    bgmAudio.pause();&lt;br /&gt;
                    bgmAudio.currentTime = 0;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 默认关闭&lt;br /&gt;
        if (!musicEnabled) {&lt;br /&gt;
            $(&#039;#wiki-bgm&#039;).remove();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15350</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15350"/>
		<updated>2026-07-31T07:13:35Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.1 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleMusic(musicEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function toggleMusic(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!bgmAudio) {&lt;br /&gt;
                    bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                    bgmAudio.loop = true;&lt;br /&gt;
                    bgmAudio.volume = 0.3;&lt;br /&gt;
                }&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                if (bgmAudio) {&lt;br /&gt;
                    bgmAudio.pause();&lt;br /&gt;
                    bgmAudio.currentTime = 0;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 默认关闭&lt;br /&gt;
        if (!musicEnabled) {&lt;br /&gt;
            $(&#039;#wiki-bgm&#039;).remove();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15349</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15349"/>
		<updated>2026-07-31T07:12:10Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.2 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
history.scrollRestoration = &#039;manual&#039;;&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleMusic(musicEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function toggleMusic(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!bgmAudio) {&lt;br /&gt;
                    bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                    bgmAudio.loop = true;&lt;br /&gt;
                    bgmAudio.volume = 0.3;&lt;br /&gt;
                }&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                if (bgmAudio) {&lt;br /&gt;
                    bgmAudio.pause();&lt;br /&gt;
                    bgmAudio.currentTime = 0;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 默认关闭&lt;br /&gt;
        if (!musicEnabled) {&lt;br /&gt;
            $(&#039;#wiki-bgm&#039;).remove();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage] &amp;amp;&amp;amp; data[currentPage] &amp;gt; 200) {&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        window.scrollTo({ top: data[currentPage], behavior: &#039;instant&#039; });&lt;br /&gt;
                    }, 300);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 200) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15347</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15347"/>
		<updated>2026-07-31T07:10:49Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.2 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleMusic(musicEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function toggleMusic(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!bgmAudio) {&lt;br /&gt;
                    bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                    bgmAudio.loop = true;&lt;br /&gt;
                    bgmAudio.volume = 0.3;&lt;br /&gt;
                }&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                if (bgmAudio) {&lt;br /&gt;
                    bgmAudio.pause();&lt;br /&gt;
                    bgmAudio.currentTime = 0;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 默认关闭&lt;br /&gt;
        if (!musicEnabled) {&lt;br /&gt;
            $(&#039;#wiki-bgm&#039;).remove();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage] &amp;amp;&amp;amp; data[currentPage] &amp;gt; 200) {&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        window.scrollTo({ top: data[currentPage], behavior: &#039;instant&#039; });&lt;br /&gt;
                    }, 300);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 200) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15346</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=MediaWiki:Common.js&amp;diff=15346"/>
		<updated>2026-07-31T07:08:02Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* v3.2 - 植物大战僵尸杂交版Wiki */&lt;br /&gt;
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */&lt;br /&gt;
// 禁止页面加载时自动滚动，但不影响用户手动滚动&lt;br /&gt;
var blockAutoScroll = true;&lt;br /&gt;
setTimeout(function() { blockAutoScroll = false; }, 500);&lt;br /&gt;
&lt;br /&gt;
var originalScrollTo = window.scrollTo;&lt;br /&gt;
window.scrollTo = function() {&lt;br /&gt;
    if (blockAutoScroll) return;&lt;br /&gt;
    originalScrollTo.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var originalScroll = window.scroll;&lt;br /&gt;
window.scroll = function() {&lt;br /&gt;
    if (blockAutoScroll) return;&lt;br /&gt;
    originalScroll.apply(this, arguments);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// 自动加载 MediaWiki:Footer 页面内容，并插入到每个页面底部&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
    const namespace = mw.config.get(&#039;wgNamespaceNumber&#039;);&lt;br /&gt;
    const action = mw.config.get(&#039;wgAction&#039;);&lt;br /&gt;
    &lt;br /&gt;
    if (namespace !== 0 || action !== &#039;view&#039;) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    fetch(&amp;quot;/api.php?action=parse&amp;amp;page=MediaWiki:Footer&amp;amp;format=json&amp;quot;)&lt;br /&gt;
        .then(res =&amp;gt; res.json())&lt;br /&gt;
        .then(data =&amp;gt; {&lt;br /&gt;
            if (data.parse &amp;amp;&amp;amp; data.parse.text) {&lt;br /&gt;
                const html = data.parse.text[&#039;*&#039;];&lt;br /&gt;
                $(&#039;#mw-content-text&#039;).append(&#039;&amp;lt;div class=&amp;quot;global-footer&amp;quot;&amp;gt;&#039; + html + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// ==================== Ctrl+Shift+Q 切换顶栏 ====================&lt;br /&gt;
(function() {&lt;br /&gt;
    var headerKey = &#039;wiki_header_visible&#039;;&lt;br /&gt;
    var headerVisible = localStorage.getItem(headerKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
    function toggleHeader() {&lt;br /&gt;
        var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
        if ($header.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        headerVisible = !headerVisible;&lt;br /&gt;
        localStorage.setItem(headerKey, headerVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (headerVisible) {&lt;br /&gt;
            $header.show();&lt;br /&gt;
            // 恢复内容区上边距&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $header.hide();&lt;br /&gt;
            // 让内容区顶到最上面&lt;br /&gt;
            $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 右下角提示&lt;br /&gt;
        var msg = headerVisible ? &#039;侧边栏已显示&#039; : &#039;侧边栏已隐藏&#039;;&lt;br /&gt;
        showToast(msg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showToast(msg) {&lt;br /&gt;
        var $toast = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, bottom: &#039;20px&#039;, right: &#039;20px&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.8)&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                padding: &#039;8px 16px&#039;, borderRadius: &#039;8px&#039;,&lt;br /&gt;
                fontSize: &#039;14px&#039;, zIndex: 99999,&lt;br /&gt;
                opacity: 0, transition: &#039;opacity 0.3s&#039;&lt;br /&gt;
            },&lt;br /&gt;
            text: msg&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;body&#039;).append($toast);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 1); }, 50);&lt;br /&gt;
        setTimeout(function() { $toast.css(&#039;opacity&#039;, 0); setTimeout(function() { $toast.remove(); }, 400); }, 1200);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // 快捷键监听&lt;br /&gt;
    $(document).on(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        if (e.ctrlKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; (e.key === &#039;q&#039; || e.key === &#039;Q&#039;)) {&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            toggleHeader();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 页面加载时恢复状态&lt;br /&gt;
    $(function() {&lt;br /&gt;
        if (!headerVisible) {&lt;br /&gt;
            var $header = $(&#039;body &amp;gt; header.mw-header, body &amp;gt; header.citizen-header&#039;);&lt;br /&gt;
            if ($header.length) {&lt;br /&gt;
                $header.hide();&lt;br /&gt;
                $(&#039;#mw-content-wrapper, .citizen-body-container, #mw-content-text&#039;).css(&#039;margin-top&#039;, &#039;0&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 自定义光标开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;) &amp;amp;&amp;amp; !/Mobi|Android|iPhone/i.test(navigator.userAgent)) {&lt;br /&gt;
        var cursorKey = &#039;wiki_custom_cursor&#039;;&lt;br /&gt;
        var cursorEnabled = localStorage.getItem(cursorKey) !== &#039;false&#039;;&lt;br /&gt;
        var cursorStyleEl = null;&lt;br /&gt;
&lt;br /&gt;
        function applyCursor(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl = document.createElement(&#039;style&#039;);&lt;br /&gt;
                    cursorStyleEl.textContent =&lt;br /&gt;
                        &#039;body, div, span, p, h1, h2, h3, h4, h5, h6, td, th, li {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/1/11/%E5%85%89%E6%A0%873.png&#039;), auto !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;a, a:hover, a:active, button, .pvzhe-card, #back-to-top, .wiki-pet, .random-plant-btn, .random-zombie-btn, .friend-btn, .msg-send-btn {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/4/42/%E5%85%89%E6%A0%87%E6%9C%89%E9%93%BE%E6%8E%A5.png&#039;), pointer !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039; +&lt;br /&gt;
                        &#039;input[type=&amp;quot;text&amp;quot;], textarea, input[type=&amp;quot;search&amp;quot;] {&#039; +&lt;br /&gt;
                            &amp;quot;cursor: url(&#039;https://new.pvzhe.wiki/images/7/78/%E5%85%89%E6%A0%87%E8%BE%93%E5%85%A5.png&#039;), text !important;&amp;quot; +&lt;br /&gt;
                        &#039;}&#039;;&lt;br /&gt;
                    document.head.appendChild(cursorStyleEl);&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                if (cursorStyleEl) {&lt;br /&gt;
                    cursorStyleEl.remove();&lt;br /&gt;
                    cursorStyleEl = null;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertCursorSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.cursor-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group cursor-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;cursor-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (cursorEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;cursor-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;自定义光标&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;自定义的光标&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#cursor-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                cursorEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(cursorKey, cursorEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                applyCursor(cursorEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyCursor(cursorEnabled);&lt;br /&gt;
&lt;br /&gt;
        var cursorObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.cursor-switch&#039;).length) {&lt;br /&gt;
                insertCursorSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        cursorObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertCursorSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
// 用户颜色、图标、状态、师徒、昵称、里程碑、公告、植物/僵尸筛选、好友、私信 主逻辑&lt;br /&gt;
$(function () {&lt;br /&gt;
    // ==================== 动态注入彩虹样式 ====================&lt;br /&gt;
    var rainbowStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    rainbowStyle.textContent =&lt;br /&gt;
        &#039;.rainbow-user {&#039; +&lt;br /&gt;
            &#039;font-weight: bold;&#039; +&lt;br /&gt;
            &#039;background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);&#039; +&lt;br /&gt;
            &#039;-webkit-background-clip: text;&#039; +&lt;br /&gt;
            &#039;-webkit-text-fill-color: transparent;&#039; +&lt;br /&gt;
            &#039;background-clip: text;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(rainbowStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 动态注入字体（只注入 @font-face，不绑定 CSS 类） ====================&lt;br /&gt;
    var fontStyle = document.createElement(&#039;style&#039;);&lt;br /&gt;
    fontStyle.textContent =&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;FZJianZhi&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/0/00/FZJZ.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039; +&lt;br /&gt;
        &#039;@font-face {&#039; +&lt;br /&gt;
            &amp;quot;font-family: &#039;Huakang POP2 W9&#039;;&amp;quot; +&lt;br /&gt;
            &amp;quot;src: url(&#039;https://new.pvzhe.wiki/images/3/37/%E5%8D%8E%E5%BA%B7POP2%E4%BD%93W9.woff2&#039;) format(&#039;woff2&#039;);&amp;quot; +&lt;br /&gt;
            &#039;font-weight: normal;&#039; +&lt;br /&gt;
            &#039;font-style: normal;&#039; +&lt;br /&gt;
            &#039;font-display: swap;&#039; +&lt;br /&gt;
        &#039;}&#039;;&lt;br /&gt;
    document.head.appendChild(fontStyle);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 配置区 ====================&lt;br /&gt;
    var mentorList = [&#039;愤怒的郎朗&#039;, &#039;Yuyaabc&#039;, &#039;虚位以待&#039;, &#039;知更鸟头号粉丝&#039;, &#039;凌玥&#039;];&lt;br /&gt;
    var newbieEditThreshold = 25;&lt;br /&gt;
    var milestoneThresholds = [10, 50, 100, 500, 1000, 2500, 5000, 10000, 20000, 50000];&lt;br /&gt;
&lt;br /&gt;
    // ==================== 辅助函数 ====================&lt;br /&gt;
    function getUserName(link) {&lt;br /&gt;
        var $span = $(link).find(&#039;span&#039;).first();&lt;br /&gt;
        if ($span.length) return $span.text().trim();&lt;br /&gt;
        return $(link).text().trim();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function isUserLink(link) {&lt;br /&gt;
        return $(link).is(&#039;a.mw-userlink&#039;) || $(link).find(&#039;span&#039;).length &amp;gt; 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getLevelIcons(editcount) {&lt;br /&gt;
        var totalStars = Math.floor(editcount / 100);&lt;br /&gt;
        if (totalStars === 0) return &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
        var crowns = Math.floor(totalStars / 125);&lt;br /&gt;
        var remaining = totalStars % 125;&lt;br /&gt;
        var suns = Math.floor(remaining / 25);&lt;br /&gt;
        remaining %= 25;&lt;br /&gt;
        var moons = Math.floor(remaining / 5);&lt;br /&gt;
        var stars = remaining % 5;&lt;br /&gt;
&lt;br /&gt;
        var icons = &#039;&#039;;&lt;br /&gt;
        if (crowns &amp;gt; 0) icons += &#039;👑&#039;.repeat(crowns);&lt;br /&gt;
        if (suns &amp;gt; 0)   icons += &#039;☀️&#039;.repeat(suns);&lt;br /&gt;
        if (moons &amp;gt; 0)  icons += &#039;🌙&#039;.repeat(moons);&lt;br /&gt;
        if (stars &amp;gt; 0)  icons += &#039;⭐&#039;.repeat(stars);&lt;br /&gt;
        return icons;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateLevelIcons($link, editcount) {&lt;br /&gt;
        var iconStr = getLevelIcons(editcount);&lt;br /&gt;
        var $iconSpan = $link.next(&#039;.user-level-icons&#039;);&lt;br /&gt;
        if (iconStr === &#039;&#039;) {&lt;br /&gt;
            $iconSpan.remove();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if ($iconSpan.length === 0) {&lt;br /&gt;
            $iconSpan = $(&#039;&amp;lt;span class=&amp;quot;user-level-icons&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($iconSpan);&lt;br /&gt;
        }&lt;br /&gt;
        $iconSpan.text(iconStr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getTitleByEditcount(ec) {&lt;br /&gt;
        if (ec &amp;gt;= 10000) return &#039;神话&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 5000)  return &#039;传奇&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 2500)  return &#039;大师&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 1000)  return &#039;专家&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 500)   return &#039;资深&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 100)   return &#039;活跃&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 50)    return &#039;入门&#039;;&lt;br /&gt;
        if (ec &amp;gt;= 10)    return &#039;新手&#039;;&lt;br /&gt;
        return &#039;萌新&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function addTitleTag($link, editcount) {&lt;br /&gt;
        if ($link.data(&#039;title-tag-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;title-tag-added&#039;, true);&lt;br /&gt;
        var title = getTitleByEditcount(editcount);&lt;br /&gt;
        var $tag = $(&#039;&amp;lt;span class=&amp;quot;user-title-tag&amp;quot;&amp;gt;&#039; + title + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($tag);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 核心：颜色 + 图标 + 状态 + 师徒 + 昵称 ====================&lt;br /&gt;
    function colorizeAndStatus($links) {&lt;br /&gt;
        if ($links.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var $fresh = $links.filter(function () {&lt;br /&gt;
            return !$(this).data(&#039;user-status-processed&#039;);&lt;br /&gt;
        });&lt;br /&gt;
        if ($fresh.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var users = [];&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            var name = getUserName(this);&lt;br /&gt;
            if (name &amp;amp;&amp;amp; users.indexOf(name) === -1) users.push(name);&lt;br /&gt;
        });&lt;br /&gt;
        if (users.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            $(this).data(&#039;user-status-processed&#039;, true);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var batchSize = 50;&lt;br /&gt;
        var batches = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; users.length; i += batchSize) {&lt;br /&gt;
            batches.push(users.slice(i, i + batchSize));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var processBatch = function (batch) {&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            return api.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;users&#039;,&lt;br /&gt;
                ususers: batch.join(&#039;|&#039;),&lt;br /&gt;
                usprop: &#039;editcount&#039;&lt;br /&gt;
            }).then(function (data) {&lt;br /&gt;
                var classMap = {};&lt;br /&gt;
                var editCountMap = {};&lt;br /&gt;
                if (data.query &amp;amp;&amp;amp; data.query.users) {&lt;br /&gt;
                    data.query.users.forEach(function (u) {&lt;br /&gt;
                        var ec = u.editcount || 0;&lt;br /&gt;
                        editCountMap[u.name] = ec;&lt;br /&gt;
                        if (ec &amp;gt;= 5000) classMap[u.name] = &#039;rainbow-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 2500) classMap[u.name] = &#039;gold-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1000) classMap[u.name] = &#039;platinum-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 500) classMap[u.name] = &#039;silver-user&#039;;&lt;br /&gt;
                        else if (ec &amp;gt;= 1) classMap[u.name] = &#039;bronze-user&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $fresh.each(function () {&lt;br /&gt;
                    var $this = $(this);&lt;br /&gt;
                    var name = getUserName(this);&lt;br /&gt;
                    var cls = classMap[name];&lt;br /&gt;
                    if (cls) {&lt;br /&gt;
                        $this.removeClass(&#039;bronze-user silver-user platinum-user gold-user rainbow-user&#039;);&lt;br /&gt;
                        $this.addClass(cls);&lt;br /&gt;
                    }&lt;br /&gt;
                    var ec = editCountMap[name];&lt;br /&gt;
                    if (typeof ec !== &#039;undefined&#039;) {&lt;br /&gt;
                        updateLevelIcons($this, ec);&lt;br /&gt;
                        var isInsideCard = $this.closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                        if (!isInsideCard) {&lt;br /&gt;
                            addTitleTag($this, ec);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var colorPromise = $.Deferred().resolve();&lt;br /&gt;
        batches.forEach(function (batch) {&lt;br /&gt;
            colorPromise = colorPromise.then(function () {&lt;br /&gt;
                return processBatch(batch);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $fresh.each(function () {&lt;br /&gt;
            if (isUserLink(this)) {&lt;br /&gt;
                var isInsideCard = $(this).closest(&#039;.citizen-menu_card-content, .citizen-userMenu&#039;).length &amp;gt; 0;&lt;br /&gt;
                if (!isInsideCard) {&lt;br /&gt;
                    var username = getUserName(this);&lt;br /&gt;
                    addStatusDot($(this), username);&lt;br /&gt;
                    addMentorTag($(this), username);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 状态圆点 ====================&lt;br /&gt;
    function addStatusDot($link, username) {&lt;br /&gt;
        if ($link.data(&#039;status-dot-added&#039;)) return;&lt;br /&gt;
        $link.data(&#039;status-dot-added&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var $dot = $(&#039;&amp;lt;span class=&amp;quot;user-status-dot status-offline&amp;quot; title=&amp;quot;离线&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
        $link.after($dot);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_user_status_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 5 * 60 * 1000) {&lt;br /&gt;
                    updateDotStyle($dot, data.lastEditTime);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;usercontribs&#039;,&lt;br /&gt;
            ucuser: username,&lt;br /&gt;
            uclimit: 1,&lt;br /&gt;
            ucprop: &#039;timestamp&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var lastEditTime = null;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.usercontribs &amp;amp;&amp;amp; data.query.usercontribs.length &amp;gt; 0) {&lt;br /&gt;
                lastEditTime = data.query.usercontribs[0].timestamp;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                lastEditTime: lastEditTime,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            updateDotStyle($dot, lastEditTime);&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateDotStyle($dot, lastEditTime) {&lt;br /&gt;
        if (!lastEditTime) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var last = new Date(lastEditTime).getTime();&lt;br /&gt;
        var diffMinutes = (Date.now() - last) / 60000;&lt;br /&gt;
        if (diffMinutes &amp;lt; 15) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;在线（15分钟内活跃）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-away&#039;).addClass(&#039;status-online&#039;);&lt;br /&gt;
        } else if (diffMinutes &amp;lt; 60) {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;近期活跃（1小时内）&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-offline status-online&#039;).addClass(&#039;status-away&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $dot.attr(&#039;title&#039;, &#039;离线&#039;);&lt;br /&gt;
            $dot.removeClass(&#039;status-online status-away&#039;).addClass(&#039;status-offline&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 师徒标签 ====================&lt;br /&gt;
    function addMentorTag($link, username) {&lt;br /&gt;
        if ($link.data(&#039;mentor-tag-added&#039;)) return;&lt;br /&gt;
        if ($link.next(&#039;.user-tag&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
        var $tag;&lt;br /&gt;
&lt;br /&gt;
        if (mentorList.indexOf(username) !== -1) {&lt;br /&gt;
            $link.data(&#039;mentor-tag-added&#039;, true);&lt;br /&gt;
            $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-mentor&amp;quot;&amp;gt;导师&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
            $link.after($tag);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($link.data(&#039;newbie-tag-checked&#039;)) return;&lt;br /&gt;
        $link.data(&#039;newbie-tag-checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
        var cacheKey = &#039;mw_newbie_check_&#039; + mw.config.get(&#039;wgDBname&#039;) + &#039;_&#039; + username;&lt;br /&gt;
        var cached = localStorage.getItem(cacheKey);&lt;br /&gt;
        var now = Date.now();&lt;br /&gt;
        if (cached) {&lt;br /&gt;
            try {&lt;br /&gt;
                var data = JSON.parse(cached);&lt;br /&gt;
                if (now - data.timestamp &amp;lt; 60 * 60 * 1000) {&lt;br /&gt;
                    if (data.editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                        $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $link.after($tag);&lt;br /&gt;
                    }&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: username,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function (data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
            localStorage.setItem(cacheKey, JSON.stringify({&lt;br /&gt;
                editcount: editcount,&lt;br /&gt;
                timestamp: now&lt;br /&gt;
            }));&lt;br /&gt;
            if (editcount &amp;lt;= newbieEditThreshold) {&lt;br /&gt;
                if ($link.next(&#039;.user-tag-newbie&#039;).length === 0) {&lt;br /&gt;
                    $tag = $(&#039;&amp;lt;span class=&amp;quot;user-tag user-tag-newbie&amp;quot;&amp;gt;新手&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $link.after($tag);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function () {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑里程碑弹窗 ====================&lt;br /&gt;
    var currentUser = mw.config.get(&#039;wgUserName&#039;);&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;users&#039;,&lt;br /&gt;
            ususers: currentUser,&lt;br /&gt;
            usprop: &#039;editcount&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var editcount = 0;&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.users &amp;amp;&amp;amp; data.query.users.length &amp;gt; 0) {&lt;br /&gt;
                editcount = data.query.users[0].editcount || 0;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var achievedMilestone = null;&lt;br /&gt;
            milestoneThresholds.forEach(function(m) {&lt;br /&gt;
                if (editcount &amp;gt;= m) achievedMilestone = m;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            if (achievedMilestone) {&lt;br /&gt;
                var storageKey = &#039;mw_milestone_shown_&#039; + currentUser + &#039;_&#039; + achievedMilestone;&lt;br /&gt;
                if (!localStorage.getItem(storageKey)) {&lt;br /&gt;
                    localStorage.setItem(storageKey, &#039;1&#039;);&lt;br /&gt;
&lt;br /&gt;
                    var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                            background: &#039;rgba(0,0,0,0.5)&#039;, &#039;z-index&#039;: 99998,&lt;br /&gt;
                            display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px 40px&#039;,&lt;br /&gt;
                            &#039;text-align&#039;: &#039;center&#039;, &#039;box-shadow&#039;: &#039;0 4px 20px rgba(0,0,0,0.3)&#039;,&lt;br /&gt;
                            &#039;max-width&#039;: &#039;400px&#039;, width: &#039;80%&#039;, position: &#039;relative&#039;&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;🎉 恭喜！&#039;,&lt;br /&gt;
                        css: { &#039;margin-bottom&#039;: &#039;15px&#039;, &#039;font-size&#039;: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $msg = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;你已达到 &#039; + achievedMilestone + &#039; 次编辑！&#039;,&lt;br /&gt;
                        css: { &#039;font-size&#039;: &#039;18px&#039;, &#039;margin-bottom&#039;: &#039;25px&#039;, color: &#039;#555&#039; }&lt;br /&gt;
                    });&lt;br /&gt;
                    var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                        text: &#039;太棒了！&#039;,&lt;br /&gt;
                        css: {&lt;br /&gt;
                            background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                            padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;, &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                        },&lt;br /&gt;
                        click: function() {&lt;br /&gt;
                            $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    $box.append($title, $msg, $btn);&lt;br /&gt;
                    $overlay.append($box);&lt;br /&gt;
                    $(&#039;body&#039;).append($overlay);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }).fail(function() {});&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 用户链接处理器启动 ====================&lt;br /&gt;
    var linkSelector = &#039;a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a&#039;;&lt;br /&gt;
    colorizeAndStatus($(linkSelector));&lt;br /&gt;
&lt;br /&gt;
    var observer = new MutationObserver(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    });&lt;br /&gt;
    observer.observe(document.body, {&lt;br /&gt;
        childList: true,&lt;br /&gt;
        subtree: true&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    setInterval(function () {&lt;br /&gt;
        colorizeAndStatus($(linkSelector));&lt;br /&gt;
    }, 3000);&lt;br /&gt;
&lt;br /&gt;
    // ==================== 植物卡片筛选 ====================&lt;br /&gt;
    if ($(&#039;#pf-name&#039;).length) {&lt;br /&gt;
        var $cards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $name = $(&#039;#pf-name&#039;);&lt;br /&gt;
        var $sunMax = $(&#039;#pf-sun-max&#039;);&lt;br /&gt;
        var $cdMax = $(&#039;#pf-cd-max&#039;);&lt;br /&gt;
        var $type = $(&#039;#pf-type&#039;);&lt;br /&gt;
        var $version = $(&#039;#pf-version&#039;);&lt;br /&gt;
        var $reset = $(&#039;#pf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterPlants() {&lt;br /&gt;
            var name = $name.val().toLowerCase();&lt;br /&gt;
            var sunRaw = $sunMax.val().trim();&lt;br /&gt;
            var cdRaw = $cdMax.val().trim();&lt;br /&gt;
            var sunTarget = sunRaw !== &#039;&#039; ? parseFloat(sunRaw) : null;&lt;br /&gt;
            var cdTarget = cdRaw !== &#039;&#039; ? parseFloat(cdRaw) : null;&lt;br /&gt;
            var type = $type.val();&lt;br /&gt;
            var version = $version.val();&lt;br /&gt;
&lt;br /&gt;
            $cards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var sun = parseFloat($card.data(&#039;sun&#039;)) || 0;&lt;br /&gt;
                var cd = parseFloat($card.data(&#039;cooldown&#039;)) || 0;&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (sunTarget !== null &amp;amp;&amp;amp; sun !== sunTarget) show = false;&lt;br /&gt;
                if (cdTarget !== null &amp;amp;&amp;amp; cd !== cdTarget) show = false;&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (s) { return s.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $name.on(&#039;input&#039;, filterPlants);&lt;br /&gt;
        $sunMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $cdMax.on(&#039;input keyup&#039;, filterPlants);&lt;br /&gt;
        $type.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $version.on(&#039;change&#039;, filterPlants);&lt;br /&gt;
        $reset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $name.val(&#039;&#039;);&lt;br /&gt;
            $sunMax.val(&#039;&#039;);&lt;br /&gt;
            $cdMax.val(&#039;&#039;);&lt;br /&gt;
            $type.val(&#039;&#039;);&lt;br /&gt;
            $version.val(&#039;&#039;);&lt;br /&gt;
            filterPlants();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 僵尸卡片筛选 ====================&lt;br /&gt;
    function getArmorArray(healthStr) {&lt;br /&gt;
        if (!healthStr || healthStr.indexOf(&#039;+&#039;) === -1) return [];&lt;br /&gt;
        var armorPart = healthStr.split(&#039;+&#039;)[0].trim();&lt;br /&gt;
        return armorPart.split(&#039;,&#039;).map(function(s) { return s.trim(); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function extractHealth(healthStr) {&lt;br /&gt;
        var matches = healthStr.match(/\d+/g);&lt;br /&gt;
        if (matches &amp;amp;&amp;amp; matches.length &amp;gt; 0) {&lt;br /&gt;
            return parseFloat(matches[matches.length - 1]) || 0;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length) {&lt;br /&gt;
        var $zcards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
        var $zname = $(&#039;#zf-name&#039;);&lt;br /&gt;
        var $healthMin = $(&#039;#zf-health-min&#039;);&lt;br /&gt;
        var $armor = $(&#039;#zf-armor&#039;);&lt;br /&gt;
        var $speed = $(&#039;#zf-speed&#039;);&lt;br /&gt;
        var $ztype = $(&#039;#zf-type&#039;);&lt;br /&gt;
        var $zversion = $(&#039;#zf-version&#039;);&lt;br /&gt;
        var $zreset = $(&#039;#zf-reset&#039;);&lt;br /&gt;
&lt;br /&gt;
        function filterZombies() {&lt;br /&gt;
            var name = $zname.val().toLowerCase();&lt;br /&gt;
            var healthRaw = $healthMin.val().trim();&lt;br /&gt;
            var healthTarget = healthRaw !== &#039;&#039; ? parseFloat(healthRaw) : null;&lt;br /&gt;
            var armor = $armor.val();&lt;br /&gt;
            var speed = $speed.val();&lt;br /&gt;
            var type = $ztype.val();&lt;br /&gt;
            var version = $zversion.val();&lt;br /&gt;
&lt;br /&gt;
            $zcards.each(function () {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var n = $card.find(&#039;.pvzhe-card-name&#039;).text().toLowerCase();&lt;br /&gt;
                var t = ($card.data(&#039;type&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var s = ($card.data(&#039;speed&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var healthStr = ($card.data(&#039;health&#039;) || &#039;&#039;).toString();&lt;br /&gt;
                var health = extractHealth(healthStr);&lt;br /&gt;
                var armors = getArmorArray(healthStr);&lt;br /&gt;
                var v = ($card.data(&#039;version&#039;) || &#039;&#039;).toString();&lt;br /&gt;
&lt;br /&gt;
                var show = true;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; n.indexOf(name) === -1) show = false;&lt;br /&gt;
                if (healthTarget !== null &amp;amp;&amp;amp; health !== healthTarget) show = false;&lt;br /&gt;
&lt;br /&gt;
                if (armor === &#039;none&#039;) {&lt;br /&gt;
                    if (armors.length &amp;gt; 0) show = false;&lt;br /&gt;
                } else if (armor) {&lt;br /&gt;
                    if (armors.indexOf(armor) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (speed) {&lt;br /&gt;
                    var cardSpeeds = s.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardSpeeds.indexOf(speed) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (type) {&lt;br /&gt;
                    var cardTypes = t.split(&#039;,&#039;).map(function (v) { return v.trim(); });&lt;br /&gt;
                    if (cardTypes.indexOf(type) === -1) show = false;&lt;br /&gt;
                }&lt;br /&gt;
                if (version &amp;amp;&amp;amp; v !== version) show = false;&lt;br /&gt;
                $card.toggleClass(&#039;hidden-card&#039;, !show);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $zname.on(&#039;input&#039;, filterZombies);&lt;br /&gt;
        $healthMin.on(&#039;input keyup&#039;, filterZombies);&lt;br /&gt;
        $armor.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $speed.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $ztype.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zversion.on(&#039;change&#039;, filterZombies);&lt;br /&gt;
        $zreset.on(&#039;click&#039;, function () {&lt;br /&gt;
            $zname.val(&#039;&#039;);&lt;br /&gt;
            $healthMin.val(&#039;&#039;);&lt;br /&gt;
            $armor.val(&#039;&#039;);&lt;br /&gt;
            $speed.val(&#039;&#039;);&lt;br /&gt;
            $ztype.val(&#039;&#039;);&lt;br /&gt;
            $zversion.val(&#039;&#039;);&lt;br /&gt;
            filterZombies();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 返回顶部按钮 ====================&lt;br /&gt;
    $(&#039;body&#039;).append(&#039;&amp;lt;button id=&amp;quot;back-to-top&amp;quot; title=&amp;quot;返回顶部&amp;quot;&amp;gt;⬆&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    var $backBtn = $(&#039;#back-to-top&#039;);&lt;br /&gt;
    $(window).scroll(function() {&lt;br /&gt;
        $backBtn.toggle($(this).scrollTop() &amp;gt; 300);&lt;br /&gt;
    });&lt;br /&gt;
    $backBtn.click(function() {&lt;br /&gt;
        $(&#039;html, body&#039;).animate({ scrollTop: 0 }, 400);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 好友系统 ====================&lt;br /&gt;
    var friendApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getFriendPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friends&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getFriendRequestsPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/friendrequests&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendList(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadFriendRequests(username, callback) {&lt;br /&gt;
        friendApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getFriendRequestsPageName(username),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveToPage(pageName, data, summary, callback) {&lt;br /&gt;
        friendApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: pageName,&lt;br /&gt;
            text: JSON.stringify(data, null, 2),&lt;br /&gt;
            summary: summary,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendFriendRequest(toUser) {&lt;br /&gt;
        if (!toUser || toUser === currentUser) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            if (myFriends.indexOf(toUser) !== -1) {&lt;br /&gt;
                alert(&#039;你们已经是好友了！&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            loadFriendRequests(toUser, function(requests) {&lt;br /&gt;
                var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                if (alreadySent) {&lt;br /&gt;
                    alert(&#039;你已经发送过好友请求了，请等待对方回应。&#039;);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                requests.push({ from: currentUser, time: Date.now() });&lt;br /&gt;
                saveToPage(getFriendRequestsPageName(toUser), requests, currentUser + &#039; 发送了好友请求&#039;, function(success) {&lt;br /&gt;
                    if (success) {&lt;br /&gt;
                        alert(&#039;好友请求已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                        updateFriendButton(toUser, &#039;pending&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function acceptFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends.push(fromUser);&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;添加好友: &#039; + fromUser, function() {&lt;br /&gt;
                loadFriendList(fromUser, function(theirFriends) {&lt;br /&gt;
                    theirFriends.push(currentUser);&lt;br /&gt;
                    saveToPage(getFriendPageName(fromUser), theirFriends, &#039;添加好友: &#039; + currentUser, function() {&lt;br /&gt;
                        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
                            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;接受好友请求&#039;, function() {&lt;br /&gt;
                                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
                                updateFriendButton(fromUser, &#039;added&#039;);&lt;br /&gt;
                            });&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function rejectFriendRequest(fromUser) {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            requests = requests.filter(function(r) { return r.from !== fromUser; });&lt;br /&gt;
            saveToPage(getFriendRequestsPageName(currentUser), requests, &#039;拒绝好友请求&#039;, function() {&lt;br /&gt;
                if ($(&#039;#friend-requests-list&#039;).length) showFriendRequests();&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function removeFriend(friendName) {&lt;br /&gt;
        if (!confirm(&#039;确定要删除好友 &#039; + friendName + &#039; 吗？&#039;)) return;&lt;br /&gt;
        loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
            myFriends = myFriends.filter(function(f) { return f !== friendName; });&lt;br /&gt;
            saveToPage(getFriendPageName(currentUser), myFriends, &#039;删除好友: &#039; + friendName, function() {&lt;br /&gt;
                loadFriendList(friendName, function(theirFriends) {&lt;br /&gt;
                    theirFriends = theirFriends.filter(function(f) { return f !== currentUser; });&lt;br /&gt;
                    saveToPage(getFriendPageName(friendName), theirFriends, &#039;删除好友: &#039; + currentUser, function() {&lt;br /&gt;
                        if ($(&#039;#friend-list-container&#039;).length) showFriendList();&lt;br /&gt;
                        updateFriendButton(friendName, &#039;add&#039;);&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateFriendButton(username, status) {&lt;br /&gt;
        var $btn = $(&#039;#friend-action-btn&#039;);&lt;br /&gt;
        if (!$btn.length) return;&lt;br /&gt;
        $btn.removeClass(&#039;friend-add-btn friend-added-btn friend-pending-btn&#039;);&lt;br /&gt;
        if (status === &#039;added&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-added-btn&#039;).text(&#039;✓ 已添加&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { removeFriend(username); });&lt;br /&gt;
        } else if (status === &#039;pending&#039;) {&lt;br /&gt;
            $btn.addClass(&#039;friend-pending-btn&#039;).text(&#039;⏳ 等待确认&#039;).off(&#039;click&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $btn.addClass(&#039;friend-add-btn&#039;).text(&#039;+ 加好友&#039;);&lt;br /&gt;
            $btn.off(&#039;click&#039;).click(function() { sendFriendRequest(username); });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendRequests() {&lt;br /&gt;
        loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
            var $list = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
            if (!$list.length) return;&lt;br /&gt;
            $list.empty();&lt;br /&gt;
            if (requests.length === 0) {&lt;br /&gt;
                $list.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无好友请求&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            requests.forEach(function(r) {&lt;br /&gt;
                var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-request-item&#039; });&lt;br /&gt;
                $item.append(&#039;&amp;lt;span&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(r.from) + &#039;&amp;quot;&amp;gt;&#039; + r.from + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                var $actions = $(&#039;&amp;lt;div&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-accept-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;接受&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $actions.append(&#039;&amp;lt;button class=&amp;quot;friend-reject-btn&amp;quot; data-from=&amp;quot;&#039; + r.from + &#039;&amp;quot;&amp;gt;拒绝&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $item.append($actions);&lt;br /&gt;
                $list.append($item);&lt;br /&gt;
            });&lt;br /&gt;
            $list.off(&#039;click&#039;).on(&#039;click&#039;, &#039;.friend-accept-btn&#039;, function() {&lt;br /&gt;
                acceptFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            }).on(&#039;click&#039;, &#039;.friend-reject-btn&#039;, function() {&lt;br /&gt;
                rejectFriendRequest($(this).data(&#039;from&#039;));&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showFriendList() {&lt;br /&gt;
        loadFriendList(currentUser, function(friends) {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-overlay&#039; });&lt;br /&gt;
                var $dialog = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;friend-dialog&#039; });&lt;br /&gt;
&lt;br /&gt;
                var realCount = friends.length;&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h3&amp;gt;👥 好友列表 &amp;lt;span class=&amp;quot;friend-count&amp;quot;&amp;gt;&#039; + realCount + &#039;人&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#f44336;cursor:pointer;&amp;quot; id=&amp;quot;friend-req-notice&amp;quot;&amp;gt;📩 有 &#039; + requests.length + &#039; 条好友请求，点击查看&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;friend-requests-list&amp;quot; style=&amp;quot;display:none;margin:10px 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                if (realCount === 0) {&lt;br /&gt;
                    $dialog.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;还没有好友，去其他用户页面加好友吧！&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    var $container = $(&#039;&amp;lt;div&amp;gt;&#039;, { id: &#039;friend-list-container&#039;, style: &#039;margin:10px 0;&#039; });&lt;br /&gt;
                    friends.forEach(function(f) {&lt;br /&gt;
                        var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039; });&lt;br /&gt;
                        $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(f) + &#039;&amp;quot;&amp;gt;&#039; + f + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; class=&amp;quot;friend-msg-link&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot; title=&amp;quot;发私信&amp;quot;&amp;gt;✉️&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                        $item.append(&#039;&amp;lt;span class=&amp;quot;friend-remove&amp;quot; data-friend=&amp;quot;&#039; + f + &#039;&amp;quot;&amp;gt; ×&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                        $container.append($item);&lt;br /&gt;
                    });&lt;br /&gt;
                    $dialog.append($container);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // ========== 推荐用户 ==========&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;h4 style=&amp;quot;margin-top:20px;border-top:1px solid #e0e0e0;padding-top:12px;&amp;quot;&amp;gt;推荐用户&amp;lt;/h4&amp;gt;&#039;);&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;div id=&amp;quot;recommend-users&amp;quot; style=&amp;quot;font-size:12px;color:#888;&amp;quot;&amp;gt;加载中...&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
                $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;allusers&#039;,&lt;br /&gt;
                    aulimit: 20,&lt;br /&gt;
                    auactiveusers: 1,&lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }, function(data) {&lt;br /&gt;
                    var allUsers = [];&lt;br /&gt;
                    if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                        data.query.allusers.forEach(function(u) {&lt;br /&gt;
                            if (u.name !== currentUser &amp;amp;&amp;amp; friends.indexOf(u.name) === -1) {&lt;br /&gt;
                                allUsers.push(u.name);&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    var $rec = $(&#039;#recommend-users&#039;).empty();&lt;br /&gt;
                    if (allUsers.length === 0) {&lt;br /&gt;
                        $rec.html(&#039;&amp;lt;span style=&amp;quot;color:#999;&amp;quot;&amp;gt;没有推荐用户&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        allUsers.slice(0, 15).forEach(function(u) {&lt;br /&gt;
                            var $item = $(&#039;&amp;lt;span&amp;gt;&#039;, { class: &#039;friend-list-item&#039;, style: &#039;cursor:pointer;&#039; });&lt;br /&gt;
                            $item.append(&#039;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u) + &#039;&amp;quot;&amp;gt;&#039; + u + &#039;&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
                            $item.append(&#039; &amp;lt;span style=&amp;quot;color:#4CAF50;font-size:11px;cursor:pointer;&amp;quot; class=&amp;quot;add-friend-btn&amp;quot; data-user=&amp;quot;&#039; + u + &#039;&amp;quot;&amp;gt;+好友&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                            $rec.append($item);&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.append(&#039;&amp;lt;button style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
                $overlay.append($dialog);&lt;br /&gt;
                $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
                $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                    if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                        $overlay.remove();&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;#friend-req-notice&#039;, function() {&lt;br /&gt;
                    var $reqList = $(&#039;#friend-requests-list&#039;);&lt;br /&gt;
                    $reqList.toggle();&lt;br /&gt;
                    if ($reqList.is(&#039;:visible&#039;)) showFriendRequests();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-remove&#039;, function() {&lt;br /&gt;
                    removeFriend($(this).data(&#039;friend&#039;));&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.friend-msg-link&#039;, function() {&lt;br /&gt;
                    var friendName = $(this).data(&#039;friend&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendMessage(friendName);&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                // 推荐用户快速加好友&lt;br /&gt;
                $dialog.on(&#039;click&#039;, &#039;.add-friend-btn&#039;, function() {&lt;br /&gt;
                    var toUser = $(this).data(&#039;user&#039;);&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    sendFriendRequest(toUser);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var pageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (pageUser !== currentUser) {&lt;br /&gt;
            var $btn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                id: &#039;friend-action-btn&#039;,&lt;br /&gt;
                class: &#039;friend-btn friend-add-btn&#039;,&lt;br /&gt;
                text: &#039;+ 加好友&#039;&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($btn);&lt;br /&gt;
&lt;br /&gt;
            loadFriendList(currentUser, function(myFriends) {&lt;br /&gt;
                if (myFriends.indexOf(pageUser) !== -1) {&lt;br /&gt;
                    updateFriendButton(pageUser, &#039;added&#039;);&lt;br /&gt;
                } else {&lt;br /&gt;
                    loadFriendRequests(pageUser, function(requests) {&lt;br /&gt;
                        var alreadySent = requests.some(function(r) { return r.from === currentUser; });&lt;br /&gt;
                        if (alreadySent) {&lt;br /&gt;
                            updateFriendButton(pageUser, &#039;pending&#039;);&lt;br /&gt;
                        } else {&lt;br /&gt;
                            $btn.click(function() { sendFriendRequest(pageUser); });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        var $userMenu = $(&#039;#pt-userpage, .citizen-userMenu&#039;).first();&lt;br /&gt;
        if ($userMenu.length) {&lt;br /&gt;
            $userMenu.after(&#039; &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; id=&amp;quot;friend-list-trigger&amp;quot; style=&amp;quot;font-size:13px;&amp;quot; title=&amp;quot;好友列表&amp;quot;&amp;gt;👥&amp;lt;/a&amp;gt;&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#friend-list-trigger&#039;, function() {&lt;br /&gt;
            showFriendList();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            loadFriendRequests(currentUser, function(requests) {&lt;br /&gt;
                var $notice = $(&#039;#friend-request-count&#039;);&lt;br /&gt;
                if (requests.length &amp;gt; 0) {&lt;br /&gt;
                    if (!$notice.length &amp;amp;&amp;amp; $(&#039;#friend-list-trigger&#039;).length) {&lt;br /&gt;
                        $(&#039;#friend-list-trigger&#039;).after(&#039;&amp;lt;span id=&amp;quot;friend-request-count&amp;quot; style=&amp;quot;color:#f44336;font-size:11px;vertical-align:super;&amp;quot;&amp;gt;&#039; + requests.length + &#039;&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    } else if ($notice.length) {&lt;br /&gt;
                        $notice.text(requests.length);&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    $notice.remove();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }, 60000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 私信系统 ====================&lt;br /&gt;
    var msgApi = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    function getMsgPageName(username) {&lt;br /&gt;
        return &#039;User:&#039; + username + &#039;/messages&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadMessages(callback) {&lt;br /&gt;
        if (!currentUser) { callback([]); return; }&lt;br /&gt;
        msgApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: getMsgPageName(currentUser),&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    try { callback(JSON.parse(pages[id].revisions[0][&#039;*&#039;])); return; } catch(e) {}&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            callback([]);&lt;br /&gt;
        }).fail(function() { callback([]); });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function saveMessages(msgs, callback) {&lt;br /&gt;
        if (!currentUser) return;&lt;br /&gt;
        msgApi.postWithEditToken({&lt;br /&gt;
            action: &#039;edit&#039;,&lt;br /&gt;
            title: getMsgPageName(currentUser),&lt;br /&gt;
            text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
            summary: &#039;更新私信&#039;,&lt;br /&gt;
            minor: true,&lt;br /&gt;
            bot: true&lt;br /&gt;
        }).then(function() {&lt;br /&gt;
            if (callback) callback(true);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            if (callback) callback(false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getUnreadCount(msgs) {&lt;br /&gt;
        var count = 0;&lt;br /&gt;
        msgs.forEach(function(m) { if (!m.read) count++; });&lt;br /&gt;
        return count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function updateMsgBadge() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var count = getUnreadCount(msgs);&lt;br /&gt;
            var $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
            if ($badge.length === 0) {&lt;br /&gt;
                var $drawer = $(&#039;.citizen-drawer&#039;).first();&lt;br /&gt;
                if ($drawer.length) {&lt;br /&gt;
                    $drawer.css(&#039;position&#039;, &#039;relative&#039;);&lt;br /&gt;
                    $drawer.append(&#039;&amp;lt;span id=&amp;quot;msg-badge&amp;quot; class=&amp;quot;msg-badge&amp;quot; title=&amp;quot;新私信&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&#039;);&lt;br /&gt;
                    $badge = $(&#039;#msg-badge&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if ($badge.length) {&lt;br /&gt;
                $badge.text(count).toggle(count &amp;gt; 0);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function showInbox() {&lt;br /&gt;
        loadMessages(function(msgs) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
            $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:15px;&amp;quot;&amp;gt;📬 私信箱&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            msgs.sort(function(a, b) { return b.time - a.time; });&lt;br /&gt;
&lt;br /&gt;
            if (msgs.length === 0) {&lt;br /&gt;
                $box.append(&#039;&amp;lt;p style=&amp;quot;color:#999;&amp;quot;&amp;gt;暂无消息&amp;lt;/p&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                msgs.forEach(function(m, index) {&lt;br /&gt;
                    var $item = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-item&#039; + (m.read ? &#039;&#039; : &#039; unread&#039;) });&lt;br /&gt;
                    var timeStr = new Date(m.time).toLocaleString(&#039;zh-CN&#039;);&lt;br /&gt;
                    $item.append(&lt;br /&gt;
                        &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;msg-sender&amp;quot;&amp;gt;&#039; + m.from + &#039;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;msg-time&amp;quot;&amp;gt;&#039; + timeStr + &#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-text&amp;quot;&amp;gt;&#039; + m.text.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;).replace(/\n/g,&#039;&amp;lt;br&amp;gt;&#039;) + &#039;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;msg-actions&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            (m.read ? &#039;&#039; : &#039;&amp;lt;button class=&amp;quot;mark-read&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;已读&amp;lt;/button&amp;gt;&#039;) +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;del-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot;&amp;gt;删除&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;button class=&amp;quot;reply-msg&amp;quot; data-index=&amp;quot;&#039; + index + &#039;&amp;quot; data-from=&amp;quot;&#039; + m.from + &#039;&amp;quot;&amp;gt;回复&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
                    );&lt;br /&gt;
                    $box.append($item);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $box.append(&#039;&amp;lt;button style=&amp;quot;margin-top:15px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;关闭&amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay) || $(e.target).text() === &#039;关闭&#039;) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.mark-read&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs[idx].read = true;&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    updateMsgBadge();&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.del-msg&#039;, function() {&lt;br /&gt;
                var idx = parseInt($(this).data(&#039;index&#039;));&lt;br /&gt;
                msgs.splice(idx, 1);&lt;br /&gt;
                saveMessages(msgs, function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    showInbox();&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.on(&#039;click&#039;, &#039;.reply-msg&#039;, function() {&lt;br /&gt;
                var toUser = $(this).data(&#039;from&#039;);&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                sendMessage(toUser);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function sendMessage(toUser) {&lt;br /&gt;
        if (!toUser) return;&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-overlay&#039; });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;msg-box&#039; });&lt;br /&gt;
        $box.append(&#039;&amp;lt;h3 style=&amp;quot;margin-bottom:10px;&amp;quot;&amp;gt;✉️ 发送私信给 &#039; + toUser + &#039;&amp;lt;/h3&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&#039;&amp;lt;textarea class=&amp;quot;msg-textarea&amp;quot; placeholder=&amp;quot;输入消息内容...&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&#039;);&lt;br /&gt;
        $box.append(&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;msg-send-submit&amp;quot; style=&amp;quot;margin-top:10px;padding:8px 20px;cursor:pointer;background:#4CAF50;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;发送&amp;lt;/button&amp;gt;&#039;,&lt;br /&gt;
            &#039;&amp;lt;button style=&amp;quot;margin-left:10px;padding:8px 20px;cursor:pointer;background:#888;color:#fff;border:none;border-radius:6px;&amp;quot;&amp;gt;取消&amp;lt;/button&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay) || $(e.target).text() === &#039;取消&#039;) {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $box.on(&#039;click&#039;, &#039;.msg-send-submit&#039;, function() {&lt;br /&gt;
            var text = $box.find(&#039;.msg-textarea&#039;).val().trim();&lt;br /&gt;
            if (!text) return;&lt;br /&gt;
            $box.find(&#039;.msg-send-submit&#039;).prop(&#039;disabled&#039;, true).text(&#039;发送中...&#039;);&lt;br /&gt;
&lt;br /&gt;
            var tempApi = new mw.Api();&lt;br /&gt;
            tempApi.get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                titles: getMsgPageName(toUser),&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                rvlimit: 1&lt;br /&gt;
            }).then(function(data) {&lt;br /&gt;
                var pages = data.query.pages;&lt;br /&gt;
                var msgs = [];&lt;br /&gt;
                for (var id in pages) {&lt;br /&gt;
                    if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                        try { msgs = JSON.parse(pages[id].revisions[0][&#039;*&#039;]); } catch(e) {}&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                msgs.push({&lt;br /&gt;
                    from: currentUser,&lt;br /&gt;
                    to: toUser,&lt;br /&gt;
                    text: text,&lt;br /&gt;
                    time: Date.now(),&lt;br /&gt;
                    read: false&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                tempApi.postWithEditToken({&lt;br /&gt;
                    action: &#039;edit&#039;,&lt;br /&gt;
                    title: getMsgPageName(toUser),&lt;br /&gt;
                    text: JSON.stringify(msgs, null, 2),&lt;br /&gt;
                    summary: currentUser + &#039; 发来一条私信&#039;,&lt;br /&gt;
                    minor: false,&lt;br /&gt;
                    bot: false&lt;br /&gt;
                }).then(function() {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;私信已发送给 &#039; + toUser + &#039;！&#039;);&lt;br /&gt;
                }).fail(function(err) {&lt;br /&gt;
                    $overlay.remove();&lt;br /&gt;
                    alert(&#039;发送失败：&#039; + (err.error &amp;amp;&amp;amp; err.error.info ? err.error.info : &#039;未知错误&#039;));&lt;br /&gt;
                });&lt;br /&gt;
            }).fail(function() {&lt;br /&gt;
                $overlay.remove();&lt;br /&gt;
                alert(&#039;发送失败，请稍后重试。&#039;);&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (mw.config.get(&#039;wgNamespaceNumber&#039;) === 2 &amp;amp;&amp;amp; mw.config.get(&#039;wgTitle&#039;).indexOf(&#039;/&#039;) === -1) {&lt;br /&gt;
        var msgPageUser = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        if (msgPageUser !== currentUser) {&lt;br /&gt;
            var $msgBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;✉️ 发送私信&#039;,&lt;br /&gt;
                class: &#039;msg-send-btn&#039;,&lt;br /&gt;
                click: function() { sendMessage(msgPageUser); }&lt;br /&gt;
            });&lt;br /&gt;
            $(&#039;#firstHeading&#039;).append($msgBtn);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        updateMsgBadge();&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-badge&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var $msgEntry = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;javascript:void(0)&#039;,&lt;br /&gt;
            id: &#039;msg-inbox-trigger&#039;,&lt;br /&gt;
            text: &#039;✉️&#039;,&lt;br /&gt;
            title: &#039;私信箱&#039;,&lt;br /&gt;
            css: { &#039;font-size&#039;: &#039;13px&#039;, &#039;margin-left&#039;: &#039;8px&#039;, &#039;cursor&#039;: &#039;pointer&#039;, &#039;text-decoration&#039;: &#039;none&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $friendTrigger = $(&#039;#friend-list-trigger&#039;);&lt;br /&gt;
        if ($friendTrigger.length) {&lt;br /&gt;
            $friendTrigger.after(&#039; &#039;);&lt;br /&gt;
            $friendTrigger.after($msgEntry);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;#msg-inbox-trigger&#039;, function() {&lt;br /&gt;
            showInbox();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            updateMsgBadge();&lt;br /&gt;
        }, 30000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 版本更新公告弹窗 ====================&lt;br /&gt;
    function checkUpdateNotice() {&lt;br /&gt;
        var $versionEl = $(&#039;.update-version&#039;);&lt;br /&gt;
        if ($versionEl.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var currentVersion = $versionEl.text().trim();&lt;br /&gt;
        if (!currentVersion) return;&lt;br /&gt;
&lt;br /&gt;
        var dismissedVersion = localStorage.getItem(&#039;mw_update_dismissed&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (dismissedVersion !== currentVersion) {&lt;br /&gt;
            var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                    background: &#039;rgba(0,0,0,0.6)&#039;, &#039;z-index&#039;: 99999,&lt;br /&gt;
                    display: &#039;flex&#039;, &#039;align-items&#039;: &#039;center&#039;, &#039;justify-content&#039;: &#039;center&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
                css: {&lt;br /&gt;
                    background: &#039;#fff&#039;, &#039;border-radius&#039;: &#039;12px&#039;, padding: &#039;30px&#039;,&lt;br /&gt;
                    &#039;max-width&#039;: &#039;550px&#039;, width: &#039;90%&#039;, &#039;max-height&#039;: &#039;80vh&#039;,&lt;br /&gt;
                    &#039;overflow-y&#039;: &#039;auto&#039;, &#039;box-shadow&#039;: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                    position: &#039;relative&#039;&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
var $content = $(&#039;&amp;lt;div&amp;gt;&#039;).css({&#039;text-align&#039;:&#039;left&#039;,&#039;font-size&#039;:&#039;14px&#039;,&#039;line-height&#039;:&#039;1.8&#039;}).html(&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:18px;font-weight:bold;margin-bottom:5px;&amp;quot;&amp;gt;【植物大战僵尸杂交版0.25.5版本更新公告】&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;div style=&amp;quot;text-align:center;font-size:12px;color:#888;margin-bottom:15px;&amp;quot;&amp;gt;植物大战僵尸杂交版（重制版）0.25.5&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;a href=&amp;quot;https://www.bilibili.com/opus/1226688839230160904?spm_id_from=333.1365.0.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;【杂交版0.25.5版本更新】&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;电脑（Windows）版链接：https://pan.quark.cn/s/4259e472de02&amp;lt;br&amp;gt;&#039; +&lt;br /&gt;
    &#039;其他版本：https://pan.quark.cn/s/a03f4fffc55b&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
            var $closeBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
                text: &#039;我知道了&#039;,&lt;br /&gt;
                css: {&lt;br /&gt;
                    display: &#039;block&#039;, margin: &#039;20px auto 0&#039;,&lt;br /&gt;
                    background: &#039;#4CAF50&#039;, color: &#039;#fff&#039;, border: &#039;none&#039;,&lt;br /&gt;
                    padding: &#039;10px 30px&#039;, &#039;border-radius&#039;: &#039;8px&#039;,&lt;br /&gt;
                    &#039;font-size&#039;: &#039;16px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
                },&lt;br /&gt;
                click: function() {&lt;br /&gt;
                    localStorage.setItem(&#039;mw_update_dismissed&#039;, currentVersion);&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            $box.append($content, $closeBtn);&lt;br /&gt;
            $overlay.append($box);&lt;br /&gt;
            $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
            $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
                if ($(e.target).is($overlay)) {&lt;br /&gt;
                    $overlay.fadeOut(300, function() { $(this).remove(); });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setTimeout(function() {&lt;br /&gt;
        checkUpdateNotice();&lt;br /&gt;
    }, 500);&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
    var posKey = &#039;mw_edit_position_&#039; + mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
    var savedPos = localStorage.getItem(posKey);&lt;br /&gt;
&lt;br /&gt;
    // 滚动时保存位置&lt;br /&gt;
    $(window).on(&#039;scroll&#039;, function() {&lt;br /&gt;
        var pos = $(window).scrollTop();&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            localStorage.setItem(posKey, pos);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 恢复位置&lt;br /&gt;
    if (savedPos &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pos = parseInt(savedPos);&lt;br /&gt;
        if (pos &amp;gt; 100) {&lt;br /&gt;
            setTimeout(function() {&lt;br /&gt;
                $(&#039;html, body&#039;).animate({ scrollTop: pos }, 300);&lt;br /&gt;
            }, 600);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
})();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 背景音乐开关 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgUserName&#039;)) {&lt;br /&gt;
        var musicKey = &#039;wiki_bgm_enabled&#039;;&lt;br /&gt;
        var musicEnabled = localStorage.getItem(musicKey) === &#039;true&#039;;&lt;br /&gt;
        var bgmAudio = null;&lt;br /&gt;
&lt;br /&gt;
        function insertMusicSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.bgm-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group bgm-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;bgm-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (musicEnabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;bgm-toggle&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;背景音乐&amp;lt;/span&amp;gt;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;开启或关闭全站背景音乐&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#bgm-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                musicEnabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(musicKey, musicEnabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleMusic(musicEnabled);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function toggleMusic(enable) {&lt;br /&gt;
            if (enable) {&lt;br /&gt;
                if (!bgmAudio) {&lt;br /&gt;
                    bgmAudio = new Audio(&#039;https://music.163.com/song/media/outer/url?id=2692379520.mp3&#039;);&lt;br /&gt;
                    bgmAudio.loop = true;&lt;br /&gt;
                    bgmAudio.volume = 0.3;&lt;br /&gt;
                }&lt;br /&gt;
                bgmAudio.play().catch(function() {&lt;br /&gt;
                    $(document).one(&#039;click&#039;, function() {&lt;br /&gt;
                        bgmAudio.play();&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                if (bgmAudio) {&lt;br /&gt;
                    bgmAudio.pause();&lt;br /&gt;
                    bgmAudio.currentTime = 0;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 默认关闭&lt;br /&gt;
        if (!musicEnabled) {&lt;br /&gt;
            $(&#039;#wiki-bgm&#039;).remove();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var musicObserver = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.bgm-switch&#039;).length) {&lt;br /&gt;
                insertMusicSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        musicObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) insertMusicSwitch();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== Wiki 宠物 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var pets = {&lt;br /&gt;
            &#039;冰瓜香蒲&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/1/10/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/4/47/%E5%86%B0%E7%93%9C%E9%A6%99%E8%92%B2%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            },&lt;br /&gt;
            &#039;小猫向日葵&#039;: {&lt;br /&gt;
                idle: &#039;https://new.pvzhe.wiki/images/9/9b/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E5%BE%85%E6%9C%BA.gif&#039;,&lt;br /&gt;
                petting: &#039;https://new.pvzhe.wiki/images/8/85/%E5%B0%8F%E7%8C%AB%E5%90%91%E6%97%A5%E8%91%B5%E6%8A%9A%E6%91%B8.gif&#039;,&lt;br /&gt;
                size: 100&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
        var petNames = Object.keys(pets);&lt;br /&gt;
        var currentPet = localStorage.getItem(&#039;wiki_pet_current&#039;) || &#039;冰瓜香蒲&#039;;&lt;br /&gt;
        if (!pets[currentPet]) currentPet = &#039;冰瓜香蒲&#039;;&lt;br /&gt;
&lt;br /&gt;
        var petState = &#039;idle&#039;;&lt;br /&gt;
        var petTimer = null;&lt;br /&gt;
        var affectionKey = &#039;wiki_pet_affection_&#039;;&lt;br /&gt;
        var positionKey = &#039;wiki_pet_position&#039;;&lt;br /&gt;
        var affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
        var affectionPerPet = 5;&lt;br /&gt;
        var affectionCooldown = 100;&lt;br /&gt;
        var lastPetTime = 0;&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var dragStartX, dragStartY, petStartX, petStartY;&lt;br /&gt;
        var hasMoved = false;&lt;br /&gt;
        var levels = [&lt;br /&gt;
            { min: 0, title: &#039;陌生&#039;, emoji: &#039;🤔&#039; },&lt;br /&gt;
            { min: 50, title: &#039;认识&#039;, emoji: &#039;👋&#039; },&lt;br /&gt;
            { min: 150, title: &#039;友好&#039;, emoji: &#039;😊&#039; },&lt;br /&gt;
            { min: 400, title: &#039;亲密&#039;, emoji: &#039;💚&#039; },&lt;br /&gt;
            { min: 1000, title: &#039;挚友&#039;, emoji: &#039;💖&#039; },&lt;br /&gt;
            { min: 2500, title: &#039;灵魂伴侣&#039;, emoji: &#039;✨&#039; }&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
        function getLevel(aff) {&lt;br /&gt;
            var lvl = levels[0];&lt;br /&gt;
            for (var i = levels.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
                if (aff &amp;gt;= levels[i].min) { lvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return lvl;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function saveAffection() { localStorage.setItem(affectionKey + currentPet, affection); }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            var pos = $pet.position();&lt;br /&gt;
            var bottom = $(window).height() - pos.top - $pet.height();&lt;br /&gt;
            localStorage.setItem(positionKey, JSON.stringify({ left: pos.left, bottom: Math.max(0, bottom) }));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function showAffectionPanel() {&lt;br /&gt;
            var lvl = getLevel(affection);&lt;br /&gt;
            var nextLvl = null;&lt;br /&gt;
            for (var i = 0; i &amp;lt; levels.length; i++) {&lt;br /&gt;
                if (affection &amp;lt; levels[i].min) { nextLvl = levels[i]; break; }&lt;br /&gt;
            }&lt;br /&gt;
            var text = lvl.emoji + &#039; &#039; + lvl.title + &#039; (&#039; + affection + &#039;)&#039;;&lt;br /&gt;
            if (nextLvl) {&lt;br /&gt;
                var progress = Math.round((affection - lvl.min) / (nextLvl.min - lvl.min) * 100);&lt;br /&gt;
                text += &#039; → &#039; + nextLvl.emoji + &#039; &#039; + progress + &#039;%&#039;;&lt;br /&gt;
            } else { text += &#039; MAX&#039;; }&lt;br /&gt;
            $affectionPanel.text(text).css(&#039;color&#039;, &#039;#fff&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function spawnHeart(x, y) {&lt;br /&gt;
            var hearts = [&#039;💚&#039;, &#039;💙&#039;, &#039;💛&#039;, &#039;💜&#039;, &#039;❤️&#039;, &#039;💖&#039;, &#039;✨&#039;];&lt;br /&gt;
            var heart = hearts[Math.floor(Math.random() * hearts.length)];&lt;br /&gt;
            var $heart = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-heart&#039;, text: heart, css: { left: x, top: y } });&lt;br /&gt;
            $(&#039;body&#039;).append($heart);&lt;br /&gt;
            setTimeout(function() { $heart.remove(); }, 1500);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function triggerLevelUp() {&lt;br /&gt;
            $pet.addClass(&#039;level-up&#039;);&lt;br /&gt;
            setTimeout(function() { $pet.removeClass(&#039;level-up&#039;); }, 800);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function switchPet(newPet) {&lt;br /&gt;
            if (newPet === currentPet) return;&lt;br /&gt;
            currentPet = newPet;&lt;br /&gt;
            localStorage.setItem(&#039;wiki_pet_current&#039;, currentPet);&lt;br /&gt;
            affection = parseInt(localStorage.getItem(affectionKey + currentPet)) || 0;&lt;br /&gt;
            $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            setPetState(&#039;idle&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var savedPos = JSON.parse(localStorage.getItem(positionKey)) || { left: 20, bottom: 20 };&lt;br /&gt;
        var $pet = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;wiki-pet&#039;,&lt;br /&gt;
            css: { opacity: 0, left: savedPos.left + &#039;px&#039;, bottom: savedPos.bottom + &#039;px&#039;, top: &#039;auto&#039;, right: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $img = $(&#039;&amp;lt;img&amp;gt;&#039;, {&lt;br /&gt;
            src: pets[currentPet].idle,&lt;br /&gt;
            alt: currentPet,&lt;br /&gt;
            draggable: &#039;false&#039;,&lt;br /&gt;
            css: { width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $affectionPanel = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-affection&#039; });&lt;br /&gt;
        var $tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;, { class: &#039;pet-tooltip&#039;, text: &#039;点击抚摸我~ 🐱&#039; });&lt;br /&gt;
        var $switchBtn = $(&#039;&amp;lt;button&amp;gt;&#039;, { class: &#039;pet-switch-btn&#039;, text: &#039;🔄&#039;, title: &#039;切换宠物&#039; });&lt;br /&gt;
        $pet.append($img, $affectionPanel, $tooltip, $switchBtn);&lt;br /&gt;
        $(&#039;body&#039;).append($pet);&lt;br /&gt;
&lt;br /&gt;
        showAffectionPanel();&lt;br /&gt;
        setTimeout(function() { $pet.animate({ opacity: 1 }, 500); }, 1000);&lt;br /&gt;
&lt;br /&gt;
        $switchBtn.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
            var idx = petNames.indexOf(currentPet);&lt;br /&gt;
            var nextIdx = (idx + 1) % petNames.length;&lt;br /&gt;
            switchPet(petNames[nextIdx]);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function setPetState(state) {&lt;br /&gt;
            if (petState === state) return;&lt;br /&gt;
            petState = state;&lt;br /&gt;
            clearTimeout(petTimer);&lt;br /&gt;
            $pet.removeClass(&#039;petting&#039;);&lt;br /&gt;
            if (state === &#039;idle&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].idle);&lt;br /&gt;
                $img.css({ width: pets[currentPet].size + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $tooltip.text(&#039;点击抚摸我~ &#039; + getLevel(affection).emoji);&lt;br /&gt;
            } else if (state === &#039;petting&#039;) {&lt;br /&gt;
                $img.attr(&#039;src&#039;, pets[currentPet].petting);&lt;br /&gt;
                var petSize = currentPet === &#039;小猫向日葵&#039; ? pets[currentPet].size * 1.2 : Math.round(pets[currentPet].size * 1.2);&lt;br /&gt;
                $img.css({ width: petSize + &#039;px&#039;, height: &#039;auto&#039; });&lt;br /&gt;
                $pet.addClass(&#039;petting&#039;);&lt;br /&gt;
                $tooltip.text(&#039;好舒服~ 💚&#039;);&lt;br /&gt;
                petTimer = setTimeout(function() { setPetState(&#039;idle&#039;); }, 1200);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
            if (e.button !== 0) return;&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = e.clientX; dragStartY = e.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mousemove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var dx = e.clientX - dragStartX, dy = e.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;mouseup&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($switchBtn)) return;&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
            if (hasMoved) return;&lt;br /&gt;
            var now = Date.now();&lt;br /&gt;
            if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
            lastPetTime = now;&lt;br /&gt;
            setPetState(&#039;petting&#039;);&lt;br /&gt;
            var oldLevel = getLevel(affection).title;&lt;br /&gt;
            affection += affectionPerPet;&lt;br /&gt;
            saveAffection();&lt;br /&gt;
            showAffectionPanel();&lt;br /&gt;
            var newLevel = getLevel(affection).title;&lt;br /&gt;
            if (newLevel !== oldLevel) {&lt;br /&gt;
                triggerLevelUp();&lt;br /&gt;
                $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
            }&lt;br /&gt;
            var offset = $pet.offset();&lt;br /&gt;
            spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            if (petState === &#039;idle&#039; &amp;amp;&amp;amp; !isDragging &amp;amp;&amp;amp; Math.random() &amp;lt; 0.3) {&lt;br /&gt;
                $pet.css(&#039;transform&#039;, &#039;scale(1.05) translateY(-5px)&#039;);&lt;br /&gt;
                setTimeout(function() { $pet.css(&#039;transform&#039;, &#039;scale(1) translateY(0)&#039;); }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        }, 10000);&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchstart&#039;, function(e) {&lt;br /&gt;
            $pet.addClass(&#039;touching&#039;);&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            isDragging = true; hasMoved = false;&lt;br /&gt;
            dragStartX = touch.clientX; dragStartY = touch.clientY;&lt;br /&gt;
            petStartX = $pet.offset().left; petStartY = $pet.offset().top;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;none&#039;);&lt;br /&gt;
            e.stopPropagation();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $pet.on(&#039;touchend&#039;, function() {&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchmove&#039;, function(e) {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            var touch = e.originalEvent.touches[0];&lt;br /&gt;
            var dx = touch.clientX - dragStartX, dy = touch.clientY - dragStartY;&lt;br /&gt;
            if (Math.abs(dx) &amp;gt; 3 || Math.abs(dy) &amp;gt; 3) hasMoved = true;&lt;br /&gt;
            var newX = Math.max(0, Math.min(petStartX + dx, window.innerWidth - pets[currentPet].size));&lt;br /&gt;
            var newY = Math.max(0, Math.min(petStartY + dy, window.innerHeight - pets[currentPet].size));&lt;br /&gt;
            $pet.css({ left: newX + &#039;px&#039;, top: newY + &#039;px&#039;, bottom: &#039;auto&#039;, right: &#039;auto&#039; });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $(document).on(&#039;touchend&#039;, function() {&lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            $pet.css(&#039;transition&#039;, &#039;transform 0.2s&#039;);&lt;br /&gt;
            $pet.removeClass(&#039;touching&#039;);&lt;br /&gt;
            savePosition();&lt;br /&gt;
            if (!hasMoved) {&lt;br /&gt;
                var now = Date.now();&lt;br /&gt;
                if (now - lastPetTime &amp;lt; affectionCooldown) return;&lt;br /&gt;
                lastPetTime = now;&lt;br /&gt;
                setPetState(&#039;petting&#039;);&lt;br /&gt;
                var oldLevel = getLevel(affection).title;&lt;br /&gt;
                affection += affectionPerPet;&lt;br /&gt;
                saveAffection();&lt;br /&gt;
                showAffectionPanel();&lt;br /&gt;
                var newLevel = getLevel(affection).title;&lt;br /&gt;
                if (newLevel !== oldLevel) {&lt;br /&gt;
                    triggerLevelUp();&lt;br /&gt;
                    $affectionPanel.text(&#039;🎉 升级！&#039; + newLevel + &#039;！&#039;).css(&#039;color&#039;, &#039;#FFD700&#039;);&lt;br /&gt;
                    setTimeout(function() { showAffectionPanel(); }, 2000);&lt;br /&gt;
                }&lt;br /&gt;
                var offset = $pet.offset();&lt;br /&gt;
                spawnHeart(offset.left + pets[currentPet].size / 3, offset.top - 10);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读位置记忆 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var storageKey = &#039;mw_readposition_enabled&#039;;&lt;br /&gt;
        var positionKey = &#039;mw_readposition_data&#039;;&lt;br /&gt;
        var enabled = localStorage.getItem(storageKey) === &#039;true&#039;;&lt;br /&gt;
&lt;br /&gt;
        function restorePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            if (data[currentPage]) {&lt;br /&gt;
                var scrollTarget = data[currentPage];&lt;br /&gt;
                $(function() {&lt;br /&gt;
                    setTimeout(function() {&lt;br /&gt;
                        $(&#039;html, body&#039;).scrollTop(scrollTarget);&lt;br /&gt;
                    }, 500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function savePosition() {&lt;br /&gt;
            if (!enabled) return;&lt;br /&gt;
            var currentPage = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
            var scrollTop = $(window).scrollTop();&lt;br /&gt;
            if (scrollTop &amp;gt; 50) {&lt;br /&gt;
                var data = JSON.parse(localStorage.getItem(positionKey) || &#039;{}&#039;);&lt;br /&gt;
                data[currentPage] = scrollTop;&lt;br /&gt;
                localStorage.setItem(positionKey, JSON.stringify(data));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.readposition-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group readposition-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;readposition-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (enabled ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;readposition-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;记住阅读位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;返回页面时恢复上次滚动位置&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#readposition-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                enabled = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(storageKey, enabled ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                if (!enabled) {&lt;br /&gt;
                    localStorage.removeItem(positionKey);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(window).on(&#039;beforeunload&#039;, function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        setInterval(function() {&lt;br /&gt;
            savePosition();&lt;br /&gt;
        }, 5000);&lt;br /&gt;
&lt;br /&gt;
        restorePosition();&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.readposition-switch&#039;).length) {&lt;br /&gt;
                    insertSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 宠物显示开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var petVisibleKey = &#039;wiki_pet_visible&#039;;&lt;br /&gt;
        var petVisible = localStorage.getItem(petVisibleKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function togglePet(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;.wiki-pet&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertPetSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.pet-visible-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group pet-visible-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;pet-visible-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (petVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;pet-visible-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;显示宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面显示Wiki宠物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#pet-visible-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                petVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(petVisibleKey, petVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                togglePet(petVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!petVisible) {&lt;br /&gt;
            var checkPet = setInterval(function() {&lt;br /&gt;
                if ($(&#039;.wiki-pet&#039;).length) {&lt;br /&gt;
                    $(&#039;.wiki-pet&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkPet);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkPet); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.pet-visible-switch&#039;).length) {&lt;br /&gt;
                    insertPetSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertPetSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 回到顶部按钮开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var backToTopKey = &#039;wiki_backtotop_visible&#039;;&lt;br /&gt;
        var backToTopVisible = localStorage.getItem(backToTopKey) !== &#039;false&#039;;&lt;br /&gt;
&lt;br /&gt;
        function toggleBackToTop(show) {&lt;br /&gt;
            if (show) {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeIn(300);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#back-to-top&#039;).fadeOut(300);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function insertBackToTopSwitch() {&lt;br /&gt;
            var $target = $(&#039;.citizen-preferences-section__content&#039;).last();&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.backtotop-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch cdx-toggle-switch--align-switch citizen-preferences-group backtotop-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input id=&amp;quot;backtotop-toggle&amp;quot; class=&amp;quot;cdx-toggle-switch__input&amp;quot; type=&amp;quot;checkbox&amp;quot; role=&amp;quot;switch&amp;quot;&#039; + (backToTopVisible ? &#039; checked&#039; : &#039;&#039;) + &#039;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-toggle-switch__switch__grip&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-label cdx-toggle-switch__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;label class=&amp;quot;cdx-label__label&amp;quot; for=&amp;quot;backtotop-toggle&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/label&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;在页面右下角显示回到顶部按钮&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.append($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#backtotop-toggle&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                backToTopVisible = $(this).is(&#039;:checked&#039;);&lt;br /&gt;
                localStorage.setItem(backToTopKey, backToTopVisible ? &#039;true&#039; : &#039;false&#039;);&lt;br /&gt;
                toggleBackToTop(backToTopVisible);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (!backToTopVisible) {&lt;br /&gt;
            var checkBtn = setInterval(function() {&lt;br /&gt;
                if ($(&#039;#back-to-top&#039;).length) {&lt;br /&gt;
                    $(&#039;#back-to-top&#039;).css({ opacity: 0, display: &#039;none&#039; });&lt;br /&gt;
                    clearInterval(checkBtn);&lt;br /&gt;
                }&lt;br /&gt;
            }, 100);&lt;br /&gt;
            setTimeout(function() { clearInterval(checkBtn); }, 5000);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function(mutations) {&lt;br /&gt;
            mutations.forEach(function(mutation) {&lt;br /&gt;
                if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.backtotop-switch&#039;).length) {&lt;br /&gt;
                    insertBackToTopSwitch();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;.citizen-preferences-section__content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertBackToTopSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
&lt;br /&gt;
    // ==================== 卡片自动计数 ====================&lt;br /&gt;
    var $allCards = $(&#039;.pvzhe-card&#039;);&lt;br /&gt;
    if ($allCards.length &amp;gt; 0) {&lt;br /&gt;
        var pageTitle = mw.config.get(&#039;wgTitle&#039;);&lt;br /&gt;
        var typeName = pageTitle.indexOf(&#039;僵尸&#039;) !== -1 ? &#039;僵尸&#039; : &#039;植物&#039;;&lt;br /&gt;
        var $counter = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            class: &#039;card-counter&#039;,&lt;br /&gt;
            text: &#039;共 &#039; + $allCards.length + &#039; 个&#039; + typeName&lt;br /&gt;
        });&lt;br /&gt;
        var $filterBox = $(&#039;.pvzhe-filter-box&#039;).first();&lt;br /&gt;
        if ($filterBox.length) {&lt;br /&gt;
            $filterBox.before($counter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 外部链接确认 ====================&lt;br /&gt;
    $(document).on(&#039;click&#039;, &#039;a&#039;, function(e) {&lt;br /&gt;
        var href = $(this).attr(&#039;href&#039;) || &#039;&#039;;&lt;br /&gt;
        if (href.indexOf(&#039;http&#039;) === 0 &amp;amp;&amp;amp; href.indexOf(window.location.hostname) === -1) {&lt;br /&gt;
            if (!confirm(&#039;即将离开本站，确定吗？&#039;)) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 字体切换开关 ====================&lt;br /&gt;
    (function() {&lt;br /&gt;
        var fontKey = &#039;wiki_font&#039;;&lt;br /&gt;
        var currentFont = localStorage.getItem(fontKey) || &#039;standard&#039;;&lt;br /&gt;
&lt;br /&gt;
function applyFont(font) {&lt;br /&gt;
    $(&#039;body&#039;).removeClass(&#039;font-cartoon font-cartoon-italic font-fzjianzhi font-handwrite font-huapop font-fzkatong font-fzcq&#039;);&lt;br /&gt;
    if (font === &#039;cartoon&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon&#039;);&lt;br /&gt;
    } else if (font === &#039;cartoon-italic&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-cartoon-italic&#039;);&lt;br /&gt;
    } else if (font === &#039;fzjianzhi&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzjianzhi&#039;);&lt;br /&gt;
    } else if (font === &#039;handwrite&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-handwrite&#039;);&lt;br /&gt;
    } else if (font === &#039;huapop&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-huapop&#039;);&lt;br /&gt;
    } else if (font === &#039;fzkatong&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzkatong&#039;);&lt;br /&gt;
    } else if (font === &#039;fzcq&#039;) {&lt;br /&gt;
        $(&#039;body&#039;).addClass(&#039;font-fzcq&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
        function insertFontSwitch() {&lt;br /&gt;
            var $target = $(&#039;#skin-client-prefs-citizen-feature-custom-width&#039;);&lt;br /&gt;
            if (!$target.length) return;&lt;br /&gt;
            if ($(&#039;.font-switch&#039;).length) return;&lt;br /&gt;
&lt;br /&gt;
var selectHtml = &#039;&amp;lt;select class=&amp;quot;cdx-select-vue__handle&amp;quot; id=&amp;quot;font-select&amp;quot; style=&amp;quot;width:100%;padding:8px;border:1px solid #ccc;border-radius:4px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;standard&amp;quot;&#039; + (currentFont === &#039;standard&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;标准&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzjianzhi&amp;quot;&#039; + (currentFont === &#039;fzjianzhi&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正剪纸&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;huapop&amp;quot;&#039; + (currentFont === &#039;huapop&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;华康POP2体W9&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzkatong&amp;quot;&#039; + (currentFont === &#039;fzkatong&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正卡通简体&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;option value=&amp;quot;fzcq&amp;quot;&#039; + (currentFont === &#039;fzcq&#039; ? &#039; selected&#039; : &#039;&#039;) + &#039;&amp;gt;方正粗倩&amp;lt;/option&amp;gt;&#039; +&lt;br /&gt;
    &#039;&amp;lt;/select&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
            var $switch = $(&lt;br /&gt;
                &#039;&amp;lt;fieldset class=&amp;quot;cdx-field cdx-field--is-fieldset citizen-preferences-group font-switch&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;legend class=&amp;quot;cdx-label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__label&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            &#039;&amp;lt;span class=&amp;quot;cdx-label__label__text&amp;quot;&amp;gt;字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;cdx-label__description&amp;quot;&amp;gt;更改Wiki显示字体&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/legend&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div class=&amp;quot;cdx-field__control&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;div class=&amp;quot;cdx-select-vue&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                            selectHtml +&lt;br /&gt;
                        &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/fieldset&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            $target.after($switch);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#font-select&#039;).on(&#039;change&#039;, function() {&lt;br /&gt;
                var font = $(this).val();&lt;br /&gt;
                localStorage.setItem(fontKey, font);&lt;br /&gt;
                applyFont(font);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        applyFont(currentFont);&lt;br /&gt;
&lt;br /&gt;
        var observer = new MutationObserver(function() {&lt;br /&gt;
            if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;) &amp;amp;&amp;amp; !$(&#039;.font-switch&#039;).length) {&lt;br /&gt;
                insertFontSwitch();&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [&#039;class&#039;, &#039;style&#039;] });&lt;br /&gt;
&lt;br /&gt;
        if ($(&#039;#citizen-preferences-content&#039;).is(&#039;:visible&#039;)) {&lt;br /&gt;
            insertFontSwitch();&lt;br /&gt;
        }&lt;br /&gt;
    })();&lt;br /&gt;
  &lt;br /&gt;
      // ==================== 404 页面美化 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgArticleId&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgNamespaceNumber&#039;) === 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgAction&#039;) === &#039;view&#039;) {&lt;br /&gt;
        var pageName = mw.config.get(&#039;wgPageName&#039;);&lt;br /&gt;
        var $overlay = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                position: &#039;fixed&#039;, top: 0, left: 0, width: &#039;100%&#039;, height: &#039;100%&#039;,&lt;br /&gt;
                background: &#039;rgba(0,0,0,0.6)&#039;, zIndex: 99999,&lt;br /&gt;
                display: &#039;flex&#039;, alignItems: &#039;center&#039;, justifyContent: &#039;center&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $box = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            css: {&lt;br /&gt;
                background: &#039;#fff&#039;, borderRadius: &#039;16px&#039;, padding: &#039;40px&#039;,&lt;br /&gt;
                textAlign: &#039;center&#039;, boxShadow: &#039;0 8px 30px rgba(0,0,0,0.4)&#039;,&lt;br /&gt;
                maxWidth: &#039;420px&#039;, width: &#039;85%&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $icon = $(&#039;&amp;lt;div&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;🚧&#039;,&lt;br /&gt;
            css: { fontSize: &#039;60px&#039;, marginBottom: &#039;15px&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $title = $(&#039;&amp;lt;h2&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;敬请期待&#039;,&lt;br /&gt;
            css: { marginBottom: &#039;10px&#039;, fontSize: &#039;24px&#039;, color: &#039;#333&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $desc = $(&#039;&amp;lt;p&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;「&#039; + pageName + &#039;」的页面还是一片荒地，快来成为第一个开拓者吧！&#039;,&lt;br /&gt;
            css: { fontSize: &#039;14px&#039;, color: &#039;#888&#039;, marginBottom: &#039;25px&#039;, lineHeight: &#039;1.6&#039; }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnEdit = $(&#039;&amp;lt;a&amp;gt;&#039;, {&lt;br /&gt;
            href: &#039;/w/&#039; + encodeURIComponent(pageName) + &#039;?action=edit&#039;,&lt;br /&gt;
            text: &#039;✏️ 编辑此页面&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                display: &#039;inline-block&#039;, padding: &#039;10px 24px&#039;, background: &#039;#4CAF50&#039;,&lt;br /&gt;
                color: &#039;#fff&#039;, borderRadius: &#039;8px&#039;, textDecoration: &#039;none&#039;,&lt;br /&gt;
                fontSize: &#039;15px&#039;, marginRight: &#039;10px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var $btnBack = $(&#039;&amp;lt;button&amp;gt;&#039;, {&lt;br /&gt;
            text: &#039;↩ 返回&#039;,&lt;br /&gt;
            css: {&lt;br /&gt;
                padding: &#039;10px 24px&#039;, background: &#039;#888&#039;, color: &#039;#fff&#039;,&lt;br /&gt;
                border: &#039;none&#039;, borderRadius: &#039;8px&#039;, fontSize: &#039;15px&#039;, cursor: &#039;pointer&#039;&lt;br /&gt;
            },&lt;br /&gt;
            click: function() {&lt;br /&gt;
                history.back();&lt;br /&gt;
                setTimeout(function() {&lt;br /&gt;
                    if ($overlay.is(&#039;:visible&#039;)) $overlay.remove();&lt;br /&gt;
                }, 500);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        $box.append($icon, $title, $desc, $btnEdit, $btnBack);&lt;br /&gt;
        $overlay.append($box);&lt;br /&gt;
        $(&#039;body&#039;).append($overlay);&lt;br /&gt;
&lt;br /&gt;
        // 点击遮罩关闭&lt;br /&gt;
        $overlay.on(&#039;click&#039;, function(e) {&lt;br /&gt;
            if ($(e.target).is($overlay)) $overlay.remove();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 页面最后编辑时间 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var api = new mw.Api();&lt;br /&gt;
        api.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            titles: mw.config.get(&#039;wgPageName&#039;),&lt;br /&gt;
            rvlimit: 1,&lt;br /&gt;
            rvprop: &#039;timestamp|user&#039;&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions) {&lt;br /&gt;
                    var rev = pages[id].revisions[0];&lt;br /&gt;
                    var editTime = new Date(rev.timestamp);&lt;br /&gt;
                    var now = new Date();&lt;br /&gt;
                    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());&lt;br /&gt;
                    var editDay = new Date(editTime.getFullYear(), editTime.getMonth(), editTime.getDate());&lt;br /&gt;
                    var diffDays = Math.floor((today - editDay) / 86400000);&lt;br /&gt;
                    &lt;br /&gt;
                    var timeStr;&lt;br /&gt;
                    if (diffDays === 0) {&lt;br /&gt;
                        timeStr = &#039;今天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else if (diffDays === 1) {&lt;br /&gt;
                        timeStr = &#039;昨天 &#039; + editTime.toLocaleTimeString(&#039;zh-CN&#039;, {hour:&#039;2-digit&#039;,minute:&#039;2-digit&#039;});&lt;br /&gt;
                    } else {&lt;br /&gt;
                        timeStr = diffDays + &#039; 天前&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var $info = $(&#039;&amp;lt;div style=&amp;quot;color:#999;font-size:12px;margin-top:20px;text-align:right;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;最后编辑：&#039; + rev.user + &#039; 于 &#039; + timeStr +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                    $(&#039;#mw-content-text&#039;).append($info);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // ==================== 稀有度筛选 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length) {&lt;br /&gt;
        var rarityMap = {&lt;br /&gt;
            &#039;white&#039;: &#039;白卡&#039;,&lt;br /&gt;
            &#039;gold&#039;: &#039;至尊金卡&#039;,&lt;br /&gt;
            &#039;diamond&#039;: &#039;臻享钻卡&#039;,&lt;br /&gt;
            &#039;rainbow&#039;: &#039;梦幻彩卡&#039;,&lt;br /&gt;
            &#039;star&#039;: &#039;星光闪卡&#039;,&lt;br /&gt;
            &#039;original&#039;: &#039;原卡&#039;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 计数&lt;br /&gt;
        var counts = { all: $(&#039;.pvzhe-card&#039;).length };&lt;br /&gt;
        $(&#039;.pvzhe-card-container[data-rarity]&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            counts[r] = $(this).find(&#039;.pvzhe-card&#039;).length;&lt;br /&gt;
        });&lt;br /&gt;
        $(&#039;.pvzhe-rarity-btn&#039;).each(function() {&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
            var label = $(this).text().replace(/\s*\(\d+\)/, &#039;&#039;);&lt;br /&gt;
            var img = $(this).find(&#039;img&#039;).length ? $(this).find(&#039;img&#039;).prop(&#039;outerHTML&#039;) : &#039;&#039;;&lt;br /&gt;
            $(this).html(img + label + &#039; (&#039; + (counts[r] || 0) + &#039;)&#039;);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // 点击&lt;br /&gt;
        $(document).on(&#039;click&#039;, &#039;.pvzhe-rarity-btn&#039;, function() {&lt;br /&gt;
            $(&#039;.pvzhe-rarity-btn&#039;).removeClass(&#039;active&#039;);&lt;br /&gt;
            $(this).addClass(&#039;active&#039;);&lt;br /&gt;
            var r = $(this).data(&#039;rarity&#039;);&lt;br /&gt;
&lt;br /&gt;
            if (r === &#039;all&#039;) {&lt;br /&gt;
                $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;flex&#039;);&lt;br /&gt;
                $(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;.pvzhe-card-container&#039;).css(&#039;display&#039;, &#039;none&#039;);&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).hide();&lt;br /&gt;
            $(&#039;.pvzhe-card-container[data-rarity=&amp;quot;&#039; + r + &#039;&amp;quot;]&#039;).css(&#039;display&#039;, &#039;flex&#039;).find(&#039;.pvzhe-card&#039;).show();&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 编辑贡献排行榜 ====================&lt;br /&gt;
    if ($(&#039;#contribution-rank&#039;).length) {&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;allusers&#039;,&lt;br /&gt;
            aulimit: 20,&lt;br /&gt;
            auprop: &#039;editcount&#039;,&lt;br /&gt;
            auactiveusers: 1,&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(data) {&lt;br /&gt;
            var users = [];&lt;br /&gt;
            if (data.query &amp;amp;&amp;amp; data.query.allusers) {&lt;br /&gt;
                data.query.allusers.forEach(function(u) {&lt;br /&gt;
                    if (u.editcount &amp;gt; 0) users.push({ name: u.name, count: u.editcount });&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
            users = users.slice(0, 10);&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-loading&#039;).hide();&lt;br /&gt;
            var $list = $(&#039;#rank-list&#039;).show().empty();&lt;br /&gt;
            users.forEach(function(u, i) {&lt;br /&gt;
                var numClass = &#039;&#039;;&lt;br /&gt;
                if (i === 0) numClass = &#039;gold&#039;;&lt;br /&gt;
                else if (i === 1) numClass = &#039;silver&#039;;&lt;br /&gt;
                else if (i === 2) numClass = &#039;bronze&#039;;&lt;br /&gt;
                $list.append(&lt;br /&gt;
                    &#039;&amp;lt;li class=&amp;quot;rank-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-num &#039; + numClass + &#039;&amp;quot;&amp;gt;&#039; + (i + 1) + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-name&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/w/User:&#039; + encodeURIComponent(u.name) + &#039;&amp;quot;&amp;gt;&#039; + u.name + &#039;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;rank-count&amp;quot;&amp;gt;&#039; + u.count + &#039; 次编辑&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
                );&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 可重置排行榜 ====================&lt;br /&gt;
    if ($(&#039;#weekly-rank-list&#039;).length) {&lt;br /&gt;
        var rankApi = new mw.Api();&lt;br /&gt;
        rankApi.get({&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: &#039;MediaWiki:RankStartDate&#039;,&lt;br /&gt;
            prop: &#039;revisions&#039;,&lt;br /&gt;
            rvprop: &#039;content&#039;,&lt;br /&gt;
            rvlimit: 1&lt;br /&gt;
        }).then(function(data) {&lt;br /&gt;
            var pages = data.query.pages;&lt;br /&gt;
            var startDate = &#039;&#039;;&lt;br /&gt;
            for (var id in pages) {&lt;br /&gt;
                if (pages[id].revisions &amp;amp;&amp;amp; pages[id].revisions[0]) {&lt;br /&gt;
                    startDate = pages[id].revisions[0][&#039;*&#039;].trim();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!startDate) {&lt;br /&gt;
                $(&#039;#weekly-rank-list&#039;).html(&#039;未设定起始日期&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#rank-period&#039;).text(startDate + &#039; 至今&#039;);&lt;br /&gt;
            var start = startDate + &#039;T00:00:00Z&#039;;&lt;br /&gt;
            var end = new Date().toISOString();&lt;br /&gt;
&lt;br /&gt;
            $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;allusers&#039;,&lt;br /&gt;
                aulimit: 30,&lt;br /&gt;
                auactiveusers: 1,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }, function(auData) {&lt;br /&gt;
                var activeUsers = [];&lt;br /&gt;
                if (auData.query &amp;amp;&amp;amp; auData.query.allusers) {&lt;br /&gt;
                    auData.query.allusers.forEach(function(u) {&lt;br /&gt;
                        if (u.name) activeUsers.push(u.name);&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                var allCounts = {};&lt;br /&gt;
                var done = 0;&lt;br /&gt;
                activeUsers.forEach(function(username) {&lt;br /&gt;
                    var totalCount = 0;&lt;br /&gt;
                    function fetchContribs(uccontinue) {&lt;br /&gt;
                        var params = {&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            list: &#039;usercontribs&#039;,&lt;br /&gt;
                            ucuser: username,&lt;br /&gt;
                            uclimit: 50,&lt;br /&gt;
                            ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                            format: &#039;json&#039;,&lt;br /&gt;
                            ucend: start&lt;br /&gt;
                        };&lt;br /&gt;
                        if (uccontinue) {&lt;br /&gt;
                            params.uccontinue = uccontinue;&lt;br /&gt;
                        } else {&lt;br /&gt;
                            params.ucstart = end;&lt;br /&gt;
                        }&lt;br /&gt;
                        $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                            if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                                totalCount += ucData.query.usercontribs.length;&lt;br /&gt;
                                if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                    fetchContribs(ucData.continue.uccontinue);&lt;br /&gt;
                                } else {&lt;br /&gt;
                                    if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                    done++;&lt;br /&gt;
                                    if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                                }&lt;br /&gt;
                            } else {&lt;br /&gt;
                                if (totalCount &amp;gt; 0) allCounts[username] = totalCount;&lt;br /&gt;
                                done++;&lt;br /&gt;
                                if (done &amp;gt;= activeUsers.length) showResult();&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
                    fetchContribs();&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                function showResult() {&lt;br /&gt;
                    var users = [];&lt;br /&gt;
                    for (var name in allCounts) users.push({ name: name, count: allCounts[name] });&lt;br /&gt;
                    users.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                    users = users.slice(0, 5);&lt;br /&gt;
&lt;br /&gt;
                    var medals = [&#039;🥇&#039;, &#039;🥈&#039;, &#039;🥉&#039;, &#039;4️⃣&#039;, &#039;5️⃣&#039;];&lt;br /&gt;
                    var html = &#039;&#039;;&lt;br /&gt;
                    users.forEach(function(u, i) {&lt;br /&gt;
                        html += medals[i] + &#039; &amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(html || &#039;暂无编辑&#039;);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if (activeUsers.length === 0) {&lt;br /&gt;
                    $(&#039;#weekly-rank-list&#039;).html(&#039;暂无活跃用户&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 图片懒加载 ====================&lt;br /&gt;
    $(&#039;img&#039;).each(function() {&lt;br /&gt;
        if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
            $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // 监听动态添加的图片（如筛选后显示的卡片）&lt;br /&gt;
    var lazyObserver = new MutationObserver(function(mutations) {&lt;br /&gt;
        mutations.forEach(function(mutation) {&lt;br /&gt;
            $(mutation.addedNodes).find(&#039;img&#039;).each(function() {&lt;br /&gt;
                if (!$(this).attr(&#039;loading&#039;)) {&lt;br /&gt;
                    $(this).attr(&#039;loading&#039;, &#039;lazy&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
    lazyObserver.observe(document.body, { childList: true, subtree: true });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 性能优化 ====================&lt;br /&gt;
    // 1. DNS 预解析&lt;br /&gt;
    $(&#039;head&#039;).append(&#039;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//new.pvzhe.wiki&amp;quot;&amp;gt;&amp;lt;link rel=&amp;quot;dns-prefetch&amp;quot; href=&amp;quot;//images.pvzhe.wiki&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
            // ==================== 我是僵尸网格生成器 ====================&lt;br /&gt;
    if ($(&#039;#grid-generate&#039;).length) {&lt;br /&gt;
        function generateGrid() {&lt;br /&gt;
            var raw = $(&#039;#grid-data&#039;).val().trim();&lt;br /&gt;
            var cols = parseInt($(&#039;#grid-cols&#039;).val()) || 9;&lt;br /&gt;
            var rows = parseInt($(&#039;#grid-rows&#039;).val()) || 5;&lt;br /&gt;
            var bg = $(&#039;#grid-bg&#039;).val() || &#039;#2d2d2d&#039;;&lt;br /&gt;
            var cellColor = $(&#039;#grid-cell&#039;).val() || &#039;#3a3a3a&#039;;&lt;br /&gt;
            var border = $(&#039;#grid-border&#039;).val() || &#039;#555555&#039;;&lt;br /&gt;
            var dividerCol = parseInt($(&#039;#grid-divider&#039;).val()) || 4;&lt;br /&gt;
            var lines = raw.split(&#039;\n&#039;);&lt;br /&gt;
            var data = {};&lt;br /&gt;
&lt;br /&gt;
            lines.forEach(function(line) {&lt;br /&gt;
                var parts = line.split(&#039;,&#039;);&lt;br /&gt;
                if (parts.length &amp;gt;= 3) {&lt;br /&gt;
                    var name = parts[0].trim();&lt;br /&gt;
                    var col = parseInt(parts[1].trim());&lt;br /&gt;
                    var row = parseInt(parts[2].trim());&lt;br /&gt;
                    if (name &amp;amp;&amp;amp; col &amp;gt;= 1 &amp;amp;&amp;amp; row &amp;gt;= 1) {&lt;br /&gt;
                        var key = row + &#039;-&#039; + col;&lt;br /&gt;
                        data[key] = name;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            var table = &#039;{| style=&amp;quot;width:100%;max-width:900px;table-layout:fixed;text-align:center;background:&#039; + bg + &#039;;border-collapse:collapse;&amp;quot;\n&#039;;&lt;br /&gt;
            table += &#039;|-\n! !!&#039;;&lt;br /&gt;
            for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                if (c === dividerCol) {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    table += &#039; 列&#039; + c + &#039; !!&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table = table.slice(0, -2) + &#039;\n&#039;;&lt;br /&gt;
&lt;br /&gt;
            for (var r = 1; r &amp;lt;= rows; r++) {&lt;br /&gt;
                table += &#039;|-\n! 行&#039; + r + &#039;\n&#039;;&lt;br /&gt;
                for (var c = 1; c &amp;lt;= cols; c++) {&lt;br /&gt;
                    var plant = data[r + &#039;-&#039; + c];&lt;br /&gt;
                    var style = &#039;height:80px;border:2px solid &#039; + border + &#039;;background:&#039; + cellColor + &#039;;&#039;;&lt;br /&gt;
                    if (c === dividerCol) {&lt;br /&gt;
                        style += &#039;border-right:4px solid red;&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (plant) {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | [[文件:&#039; + plant + &#039;.png|50px|link=&#039; + plant + &#039;]]\n&#039;;&lt;br /&gt;
                    } else {&lt;br /&gt;
                        table += &#039;| style=&amp;quot;&#039; + style + &#039;&amp;quot; | \n&#039;;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            table += &#039;|}&#039;;&lt;br /&gt;
&lt;br /&gt;
            $(&#039;#grid-preview&#039;).html(&#039;&amp;lt;pre style=&amp;quot;background:#f9f9f9;padding:10px;border-radius:6px;font-size:12px;max-height:400px;overflow:auto;&amp;quot;&amp;gt;&#039; + table.replace(/&amp;lt;/g,&#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g,&#039;&amp;amp;gt;&#039;) + &#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
            $(&#039;#grid-preview&#039;).data(&#039;code&#039;, table);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $(&#039;#grid-generate&#039;).click(generateGrid);&lt;br /&gt;
        $(&#039;#grid-copy&#039;).click(function() {&lt;br /&gt;
            var code = $(&#039;#grid-preview&#039;).data(&#039;code&#039;);&lt;br /&gt;
            if (code) {&lt;br /&gt;
                navigator.clipboard.writeText(code).then(function() {&lt;br /&gt;
                    $(&#039;#grid-copy&#039;).text(&#039;✅ 已复制&#039;);&lt;br /&gt;
                    setTimeout(function() { $(&#039;#grid-copy&#039;).text(&#039;复制代码&#039;); }, 1500);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        generateGrid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机植物挑战 ====================&lt;br /&gt;
    if ($(&#039;#pvzhe-rarity-filter&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;植物&#039;) {&lt;br /&gt;
        var $box = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-plant-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#4CAF50;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-plant-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个植物&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-plant-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#pvzhe-rarity-filter&#039;).after($box);&lt;br /&gt;
&lt;br /&gt;
        $box.find(&#039;.random-plant-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($box.find(&#039;.random-plant-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $box.find(&#039;.random-plant-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $box.find(&#039;.random-plant-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 随机僵尸挑战 ====================&lt;br /&gt;
    if ($(&#039;#zf-name&#039;).length &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) === &#039;僵尸&#039;) {&lt;br /&gt;
        var $zbox = $(&lt;br /&gt;
            &#039;&amp;lt;div class=&amp;quot;random-plant-box&amp;quot; style=&amp;quot;text-align:center;padding:20px;background:#fff;border-radius:12px;border:2px solid #e0e0e0;margin:15px 0;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div style=&amp;quot;display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:15px;flex-wrap:wrap;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;button class=&amp;quot;random-zombie-btn&amp;quot; style=&amp;quot;padding:10px 30px;font-size:16px;background:#7E57C2;color:#fff;border:none;border-radius:8px;cursor:pointer;&amp;quot;&amp;gt;随机抽取&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;input type=&amp;quot;number&amp;quot; class=&amp;quot;random-zombie-count&amp;quot; value=&amp;quot;5&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;10&amp;quot; style=&amp;quot;width:60px;padding:8px;border:1px solid #ccc;border-radius:8px;text-align:center;font-size:16px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:14px;color:#888;&amp;quot;&amp;gt;个僵尸&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;div class=&amp;quot;random-zombie-result&amp;quot; style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
        );&lt;br /&gt;
        $(&#039;#zf-name&#039;).closest(&#039;.pvzhe-filter-box&#039;).before($zbox);&lt;br /&gt;
&lt;br /&gt;
        $zbox.find(&#039;.random-zombie-btn&#039;).click(function() {&lt;br /&gt;
            var count = parseInt($zbox.find(&#039;.random-zombie-count&#039;).val()) || 5;&lt;br /&gt;
            count = Math.max(1, Math.min(10, count));&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-count&#039;).val(count);&lt;br /&gt;
&lt;br /&gt;
            var cards = [];&lt;br /&gt;
            $(&#039;.pvzhe-card&#039;).each(function() {&lt;br /&gt;
                var $card = $(this);&lt;br /&gt;
                var name = $card.find(&#039;.pvzhe-card-name&#039;).text().trim();&lt;br /&gt;
                var img = $card.find(&#039;img&#039;).attr(&#039;src&#039;);&lt;br /&gt;
                var bg = $card.css(&#039;background&#039;) || $card.css(&#039;background-color&#039;) || &#039;#f9f9f9&#039;;&lt;br /&gt;
                var border = $card.css(&#039;border-color&#039;) || &#039;#e0e0e0&#039;;&lt;br /&gt;
                if (name &amp;amp;&amp;amp; img) {&lt;br /&gt;
                    cards.push({ name: name, img: img, bg: bg, border: border });&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
            cards = cards.sort(function() { return Math.random() - 0.5; });&lt;br /&gt;
            var picked = cards.slice(0, count);&lt;br /&gt;
            var html = &#039;&amp;lt;div style=&amp;quot;display:flex;flex-wrap:wrap;justify-content:center;gap:15px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            picked.forEach(function(c) {&lt;br /&gt;
                html += &#039;&amp;lt;a href=&amp;quot;/w/&#039; + encodeURIComponent(c.name) + &#039;&amp;quot; style=&amp;quot;text-align:center;text-decoration:none;color:#333;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;div style=&amp;quot;width:90px;height:90px;border-radius:12px;padding:4px;background:&#039; + c.bg + &#039;;border:2px solid &#039; + c.border + &#039;;display:flex;align-items:center;justify-content:center;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;img src=&amp;quot;&#039; + c.img + &#039;&amp;quot; style=&amp;quot;max-width:80px;max-height:80px;border-radius:8px;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/div&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;span style=&amp;quot;font-size:12px;margin-top:4px;display:block;&amp;quot;&amp;gt;&#039; + c.name + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
            $zbox.find(&#039;.random-zombie-result&#039;).html(html);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 修复浏览量文字 ====================&lt;br /&gt;
    $(window).on(&#039;load&#039;, function() {&lt;br /&gt;
        $(&#039;body *&#039;).contents().filter(function() {&lt;br /&gt;
            return this.nodeType === 3 &amp;amp;&amp;amp; this.textContent.indexOf(&#039;浏览量&#039;) !== -1;&lt;br /&gt;
        }).each(function() {&lt;br /&gt;
            this.textContent = this.textContent.replace(/浏览量/g, &#039;浏览量&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ==================== 侧边栏批量上传入口 ====================&lt;br /&gt;
    if ($(&#039;#citizen-drawer__card&#039;).length) {&lt;br /&gt;
        var $uploadLi = $(&#039;#t-upload&#039;).closest(&#039;li&#039;);&lt;br /&gt;
        if ($uploadLi.length) {&lt;br /&gt;
            var $batchLi = $(&lt;br /&gt;
                &#039;&amp;lt;li id=&amp;quot;n-batchupload&amp;quot; class=&amp;quot;mw-list-item&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;a href=&amp;quot;/w/%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
                        &#039;&amp;lt;span class=&amp;quot;citizen-ui-icon mw-ui-icon-image mw-ui-icon-wikimedia-image&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; &#039; +&lt;br /&gt;
                        &#039;&amp;lt;span&amp;gt;批量上传图片&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
                    &#039;&amp;lt;/a&amp;gt;&#039; +&lt;br /&gt;
                &#039;&amp;lt;/li&amp;gt;&#039;&lt;br /&gt;
            );&lt;br /&gt;
            $uploadLi.after($batchLi);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 今日活跃用户 ====================&lt;br /&gt;
    if ($(&#039;#today-active-users&#039;).length) {&lt;br /&gt;
        var now = new Date();&lt;br /&gt;
        $(&#039;#today-date&#039;).text(now.toLocaleDateString(&#039;zh-CN&#039;));&lt;br /&gt;
&lt;br /&gt;
        var chinaMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);&lt;br /&gt;
        var chinaMidnightTime = chinaMidnight.getTime();&lt;br /&gt;
&lt;br /&gt;
        $.getJSON(mw.util.wikiScript(&#039;api&#039;), {&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            list: &#039;recentchanges&#039;,&lt;br /&gt;
            rcprop: &#039;user|timestamp&#039;,&lt;br /&gt;
            rclimit: 1000,&lt;br /&gt;
            rcstart: now.toISOString(),&lt;br /&gt;
            rcend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString(),&lt;br /&gt;
            format: &#039;json&#039;&lt;br /&gt;
        }, function(rcData) {&lt;br /&gt;
            var userSet = {};&lt;br /&gt;
            if (rcData.query &amp;amp;&amp;amp; rcData.query.recentchanges) {&lt;br /&gt;
                rcData.query.recentchanges.forEach(function(rc) {&lt;br /&gt;
                    var rcTime = new Date(rc.timestamp).getTime();&lt;br /&gt;
                    if (rcTime &amp;gt;= chinaMidnightTime &amp;amp;&amp;amp; rc.user) {&lt;br /&gt;
                        if (!userSet[rc.user]) userSet[rc.user] = 0;&lt;br /&gt;
                        userSet[rc.user]++;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var users = Object.keys(userSet);&lt;br /&gt;
            if (users.length === 0) {&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(&#039;暂无编辑&#039;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            var exactCounts = {};&lt;br /&gt;
            var done = 0;&lt;br /&gt;
&lt;br /&gt;
            users.forEach(function(username) {&lt;br /&gt;
                var count = 0;&lt;br /&gt;
                function fetch(uccontinue) {&lt;br /&gt;
                    var params = {&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        list: &#039;usercontribs&#039;,&lt;br /&gt;
                        ucuser: username,&lt;br /&gt;
                        uclimit: 50,&lt;br /&gt;
                        ucprop: &#039;timestamp&#039;,&lt;br /&gt;
                        format: &#039;json&#039;,&lt;br /&gt;
                        ucend: new Date(chinaMidnightTime - 8 * 60 * 60 * 1000).toISOString()&lt;br /&gt;
                    };&lt;br /&gt;
                    if (uccontinue) params.uccontinue = uccontinue;&lt;br /&gt;
&lt;br /&gt;
                    $.getJSON(mw.util.wikiScript(&#039;api&#039;), params, function(ucData) {&lt;br /&gt;
                        if (ucData.query &amp;amp;&amp;amp; ucData.query.usercontribs) {&lt;br /&gt;
                            ucData.query.usercontribs.forEach(function(uc) {&lt;br /&gt;
                                if (new Date(uc.timestamp).getTime() &amp;gt;= chinaMidnightTime) {&lt;br /&gt;
                                    count++;&lt;br /&gt;
                                }&lt;br /&gt;
                            });&lt;br /&gt;
                            if (ucData.continue &amp;amp;&amp;amp; ucData.continue.uccontinue) {&lt;br /&gt;
                                fetch(ucData.continue.uccontinue);&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        if (count &amp;gt; 0) exactCounts[username] = count;&lt;br /&gt;
                        done++;&lt;br /&gt;
                        if (done &amp;gt;= users.length) showResult();&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                fetch();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            function showResult() {&lt;br /&gt;
                var sorted = [];&lt;br /&gt;
                for (var name in exactCounts) sorted.push({ name: name, count: exactCounts[name] });&lt;br /&gt;
                sorted.sort(function(a, b) { return b.count - a.count; });&lt;br /&gt;
                var html = &#039;&#039;;&lt;br /&gt;
                if (sorted.length === 0) {&lt;br /&gt;
                    html = &#039;暂无编辑&#039;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    sorted.forEach(function(u) {&lt;br /&gt;
                        html += &#039;&amp;lt;b&amp;gt;&#039; + u.name + &#039;&amp;lt;/b&amp;gt;：&#039; + u.count + &#039; 次&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                    });&lt;br /&gt;
                }&lt;br /&gt;
                $(&#039;#today-active-users&#039;).html(html);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ==================== 阅读计时器 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;view&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgIsArticle&#039;)) {&lt;br /&gt;
        var startTime = Date.now();&lt;br /&gt;
        var $timer = $(&#039;&amp;lt;span&amp;gt;&#039;, {&lt;br /&gt;
            style: &#039;color:#999;font-size:12px;&#039;,&lt;br /&gt;
            text: &#039;已阅 00:00&#039;&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        var waitForEditInfo = setInterval(function() {&lt;br /&gt;
            var $editInfo = $(&#039;#mw-content-text&#039;).find(&#039;div:contains(&amp;quot;最后编辑&amp;quot;)&#039;).last();&lt;br /&gt;
            if ($editInfo.length) {&lt;br /&gt;
                clearInterval(waitForEditInfo);&lt;br /&gt;
                $editInfo.css(&#039;display&#039;, &#039;flex&#039;).css(&#039;justify-content&#039;, &#039;space-between&#039;);&lt;br /&gt;
                $editInfo.prepend($timer);&lt;br /&gt;
&lt;br /&gt;
                setInterval(function() {&lt;br /&gt;
                    var elapsed = Math.floor((Date.now() - startTime) / 1000);&lt;br /&gt;
                    var h = Math.floor(elapsed / 3600);&lt;br /&gt;
                    var m = Math.floor((elapsed % 3600) / 60);&lt;br /&gt;
                    var s = elapsed % 60;&lt;br /&gt;
                    if (h &amp;gt; 0) {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (h &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + h + &#039;:&#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        $timer.text(&#039;已阅 &#039; + (m &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + m + &#039;:&#039; + (s &amp;lt; 10 ? &#039;0&#039; : &#039;&#039;) + s);&lt;br /&gt;
                    }&lt;br /&gt;
                }, 1000);&lt;br /&gt;
            }&lt;br /&gt;
        }, 200);&lt;br /&gt;
        setTimeout(function() { clearInterval(waitForEditInfo); }, 10000);&lt;br /&gt;
    }&lt;br /&gt;
    // ==================== 编辑框字数统计 ====================&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) === &#039;edit&#039; || mw.config.get(&#039;wgAction&#039;) === &#039;submit&#039;) {&lt;br /&gt;
        var updateCounter = function() {&lt;br /&gt;
            var text = $(&#039;#wpTextbox1&#039;).val();&lt;br /&gt;
            if ($(&#039;#wikiEditor-ui-toolbar&#039;).length) {&lt;br /&gt;
                // WikiEditor 启用时，从它的 iframe 获取内容&lt;br /&gt;
                var iframe = $(&#039;#wpTextbox1_ifr&#039;);&lt;br /&gt;
                if (iframe.length) {&lt;br /&gt;
                    text = iframe[0].contentDocument.body.innerText || &#039;&#039;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (!$(&#039;#edit-counter&#039;).length) {&lt;br /&gt;
                $(&#039;#wpTextbox1&#039;).after(&#039;&amp;lt;div id=&amp;quot;edit-counter&amp;quot; style=&amp;quot;color:#888;font-size:12px;margin-top:4px;text-align:right;&amp;quot;&amp;gt;字数：&#039; + text.length + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $(&#039;#edit-counter&#039;).text(&#039;字数：&#039; + text.length);&lt;br /&gt;
            }&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // 定时更新&lt;br /&gt;
        setInterval(updateCounter, 50);&lt;br /&gt;
        // 初始显示&lt;br /&gt;
        updateCounter();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}); // 结束主 $(function () { ... })&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E5%95%8A%E5%95%8A%E5%95%8A&amp;diff=15342</id>
		<title>啊啊啊</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E5%95%8A%E5%95%8A%E5%95%8A&amp;diff=15342"/>
		<updated>2026-07-31T06:57:13Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;display: flex; justify-content: center;&amp;quot;&amp;gt;&lt;br /&gt;
{{资料卡片&lt;br /&gt;
|图片=愤怒的郎朗.jpg&lt;br /&gt;
|图片宽度=100px&lt;br /&gt;
|图片介绍=咕咕嘎嘎！&lt;br /&gt;
|标题栏颜色=green&lt;br /&gt;
|属性1=名称&lt;br /&gt;
|属性1内容=愤怒的郎朗&lt;br /&gt;
|属性2=类型&lt;br /&gt;
|属性2内容=人？&lt;br /&gt;
|属性3=爱好&lt;br /&gt;
|属性3内容=无&lt;br /&gt;
|额外属性1=相关内容&lt;br /&gt;
|额外属性1内容=[[User:愤怒的郎朗|愤怒的郎朗]]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15341</id>
		<title>模板:资料卡片</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15341"/>
		<updated>2026-07-31T06:56:37Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable information&amp;quot; style=&amp;quot;margin: 0 auto !important; border: 1px solid #aaa; float: none !important; display: table !important;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;padding:0px&amp;quot; | {{#if:{{{图片|}}}|[[file:{{{图片}}}|{{{图片宽度|280px}}}]]}}{{#if:{{{图片介绍|}}}|&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;text-align:center;&amp;quot;&amp;gt;{{{图片介绍|}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
! colspan=2 style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}}&amp;quot; | &#039;&#039;&#039;基本资料&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性1|}}} | &lt;br /&gt;
! style=&amp;quot;width:60px&amp;quot; {{!}} {{{属性1|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性2|}}} | &lt;br /&gt;
! {{{属性2|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性2内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性3|}}} | &lt;br /&gt;
! {{{属性3|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性3内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性4|}}} | &lt;br /&gt;
! {{{属性4|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性4内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性5|}}} | &lt;br /&gt;
! {{{属性5|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性5内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性6|}}} | &lt;br /&gt;
! {{{属性6|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性6内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性7|}}} | &lt;br /&gt;
! {{{属性7|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性7内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性8|}}} | &lt;br /&gt;
! {{{属性8|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性8内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性10|}}} | &lt;br /&gt;
! {{{属性10|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性10内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性11|}}} | &lt;br /&gt;
! {{{属性11|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性11内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性12|}}} | &lt;br /&gt;
! {{{属性12|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性12内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性13|}}} | &lt;br /&gt;
! {{{属性13|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性13内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性14|}}} | &lt;br /&gt;
! {{{属性14|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性14内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性15|}}} | &lt;br /&gt;
! {{{属性15|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性15内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性16|}}} | &lt;br /&gt;
! {{{属性16|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性16内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性18|}}} | &lt;br /&gt;
! {{{属性18|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性18内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性19|}}} | &lt;br /&gt;
! {{{属性19|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性19内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性20|}}} | &lt;br /&gt;
! {{{属性20|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性20内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} |&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  style=&amp;quot;background-color:{{{标题栏颜色|}}};&amp;quot; {{!}}  &#039;&#039;&#039;{{{额外属性1|}}}&#039;&#039;&#039;}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} | &lt;br /&gt;
{{!}} colspan=&amp;quot;2&amp;quot;  style=&amp;quot;text-align:center;&amp;quot; {{!}} {{{额外属性1内容|}}}}}&lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{面包屑|模板}}{{模板说明}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15340</id>
		<title>模板:资料卡片</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15340"/>
		<updated>2026-07-31T06:55:12Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable information&amp;quot; style=&amp;quot;margin: 0 auto; border: 1px solid #aaa; float: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;padding:0px&amp;quot; | {{#if:{{{图片|}}}|[[file:{{{图片}}}|{{{图片宽度|280px}}}]]}}{{#if:{{{图片介绍|}}}|&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;text-align:center;&amp;quot;&amp;gt;{{{图片介绍|}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
! colspan=2 style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}}&amp;quot; | &#039;&#039;&#039;基本资料&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性1|}}} | &lt;br /&gt;
! style=&amp;quot;width:60px&amp;quot; {{!}} {{{属性1|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性2|}}} | &lt;br /&gt;
! {{{属性2|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性2内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性3|}}} | &lt;br /&gt;
! {{{属性3|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性3内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性4|}}} | &lt;br /&gt;
! {{{属性4|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性4内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性5|}}} | &lt;br /&gt;
! {{{属性5|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性5内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性6|}}} | &lt;br /&gt;
! {{{属性6|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性6内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性7|}}} | &lt;br /&gt;
! {{{属性7|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性7内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性8|}}} | &lt;br /&gt;
! {{{属性8|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性8内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性10|}}} | &lt;br /&gt;
! {{{属性10|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性10内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性11|}}} | &lt;br /&gt;
! {{{属性11|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性11内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性12|}}} | &lt;br /&gt;
! {{{属性12|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性12内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性13|}}} | &lt;br /&gt;
! {{{属性13|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性13内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性14|}}} | &lt;br /&gt;
! {{{属性14|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性14内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性15|}}} | &lt;br /&gt;
! {{{属性15|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性15内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性16|}}} | &lt;br /&gt;
! {{{属性16|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性16内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性18|}}} | &lt;br /&gt;
! {{{属性18|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性18内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性19|}}} | &lt;br /&gt;
! {{{属性19|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性19内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性20|}}} | &lt;br /&gt;
! {{{属性20|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性20内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} |&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  style=&amp;quot;background-color:{{{标题栏颜色|}}};&amp;quot; {{!}}  &#039;&#039;&#039;{{{额外属性1|}}}&#039;&#039;&#039;}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} | &lt;br /&gt;
{{!}} colspan=&amp;quot;2&amp;quot;  style=&amp;quot;text-align:center;&amp;quot; {{!}} {{{额外属性1内容|}}}}}&lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{面包屑|模板}}{{模板说明}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15339</id>
		<title>模板:资料卡片</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15339"/>
		<updated>2026-07-31T06:54:13Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable information&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto;{{{位置|}}};&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;padding:0px&amp;quot; | {{#if:{{{图片|}}}|[[file:{{{图片}}}|{{{图片宽度|280px}}}]]}}{{#if:{{{图片介绍|}}}|&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;text-align:center;&amp;quot;&amp;gt;{{{图片介绍|}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
! colspan=2 style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}}&amp;quot; | &#039;&#039;&#039;基本资料&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性1|}}} | &lt;br /&gt;
! style=&amp;quot;width:60px&amp;quot; {{!}} {{{属性1|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性2|}}} | &lt;br /&gt;
! {{{属性2|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性2内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性3|}}} | &lt;br /&gt;
! {{{属性3|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性3内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性4|}}} | &lt;br /&gt;
! {{{属性4|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性4内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性5|}}} | &lt;br /&gt;
! {{{属性5|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性5内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性6|}}} | &lt;br /&gt;
! {{{属性6|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性6内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性7|}}} | &lt;br /&gt;
! {{{属性7|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性7内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性8|}}} | &lt;br /&gt;
! {{{属性8|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性8内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性10|}}} | &lt;br /&gt;
! {{{属性10|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性10内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性11|}}} | &lt;br /&gt;
! {{{属性11|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性11内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性12|}}} | &lt;br /&gt;
! {{{属性12|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性12内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性13|}}} | &lt;br /&gt;
! {{{属性13|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性13内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性14|}}} | &lt;br /&gt;
! {{{属性14|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性14内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性15|}}} | &lt;br /&gt;
! {{{属性15|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性15内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性16|}}} | &lt;br /&gt;
! {{{属性16|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性16内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性18|}}} | &lt;br /&gt;
! {{{属性18|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性18内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性19|}}} | &lt;br /&gt;
! {{{属性19|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性19内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性20|}}} | &lt;br /&gt;
! {{{属性20|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性20内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} |&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  style=&amp;quot;background-color:{{{标题栏颜色|}}};&amp;quot; {{!}}  &#039;&#039;&#039;{{{额外属性1|}}}&#039;&#039;&#039;}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} | &lt;br /&gt;
{{!}} colspan=&amp;quot;2&amp;quot;  style=&amp;quot;text-align:center;&amp;quot; {{!}} {{{额外属性1内容|}}}}}&lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{面包屑|模板}}{{模板说明}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E5%95%8A%E5%95%8A%E5%95%8A&amp;diff=15338</id>
		<title>啊啊啊</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E5%95%8A%E5%95%8A%E5%95%8A&amp;diff=15338"/>
		<updated>2026-07-31T06:52:04Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{资料卡片&lt;br /&gt;
|位置=auto&lt;br /&gt;
|图片=愤怒的郎朗.jpg&lt;br /&gt;
|图片宽度=100px&lt;br /&gt;
|图片介绍=咕咕嘎嘎！&lt;br /&gt;
|标题栏颜色=green&lt;br /&gt;
|属性1=名称&lt;br /&gt;
|属性1内容=愤怒的郎朗&lt;br /&gt;
|属性2=类型&lt;br /&gt;
|属性2内容=人？&lt;br /&gt;
|属性3=爱好&lt;br /&gt;
|属性3内容=无&lt;br /&gt;
|额外属性1=相关内容&lt;br /&gt;
|额外属性1内容=[[User:愤怒的郎朗|愤怒的郎朗]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15337</id>
		<title>模板:资料卡片</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15337"/>
		<updated>2026-07-31T06:51:25Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable information&amp;quot; style=&amp;quot;margin:{{{位置|auto}}};&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;padding:0px&amp;quot; | {{#if:{{{图片|}}}|[[file:{{{图片}}}|{{{图片宽度|280px}}}]]}}{{#if:{{{图片介绍|}}}|&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;text-align:center;&amp;quot;&amp;gt;{{{图片介绍|}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
! colspan=2 style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}}&amp;quot; | &#039;&#039;&#039;基本资料&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性1|}}} | &lt;br /&gt;
! style=&amp;quot;width:60px&amp;quot; {{!}} {{{属性1|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性2|}}} | &lt;br /&gt;
! {{{属性2|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性2内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性3|}}} | &lt;br /&gt;
! {{{属性3|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性3内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性4|}}} | &lt;br /&gt;
! {{{属性4|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性4内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性5|}}} | &lt;br /&gt;
! {{{属性5|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性5内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性6|}}} | &lt;br /&gt;
! {{{属性6|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性6内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性7|}}} | &lt;br /&gt;
! {{{属性7|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性7内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性8|}}} | &lt;br /&gt;
! {{{属性8|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性8内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性10|}}} | &lt;br /&gt;
! {{{属性10|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性10内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性11|}}} | &lt;br /&gt;
! {{{属性11|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性11内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性12|}}} | &lt;br /&gt;
! {{{属性12|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性12内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性13|}}} | &lt;br /&gt;
! {{{属性13|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性13内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性14|}}} | &lt;br /&gt;
! {{{属性14|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性14内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性15|}}} | &lt;br /&gt;
! {{{属性15|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性15内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性16|}}} | &lt;br /&gt;
! {{{属性16|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性16内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性17|}}} | &lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性18|}}} | &lt;br /&gt;
! {{{属性18|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性18内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性19|}}} | &lt;br /&gt;
! {{{属性19|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性19内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{属性20|}}} | &lt;br /&gt;
! {{{属性20|}}}&lt;br /&gt;
{{!}} {{!}} {{{属性20内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} |&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  style=&amp;quot;background-color:{{{标题栏颜色|}}};&amp;quot; {{!}}  &#039;&#039;&#039;{{{额外属性1|}}}&#039;&#039;&#039;}}&lt;br /&gt;
|-&lt;br /&gt;
{{ #if: {{{额外属性1|}}} | &lt;br /&gt;
{{!}} colspan=&amp;quot;2&amp;quot;  style=&amp;quot;text-align:center;&amp;quot; {{!}} {{{额外属性1内容|}}}}}&lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{面包屑|模板}}{{模板说明}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15334</id>
		<title>模板:资料卡片</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15334"/>
		<updated>2026-07-31T06:49:23Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{| class=&amp;quot;wikitable information&amp;quot; style=&amp;quot;margin: auto;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;padding:0px&amp;quot; | {{#if:{{{图片|}}}|[[file:{{{图片}}}|{{{图片宽度|280px}}}]]}}{{#if:{{{图片介绍|}}}|&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;text-align:center;&amp;quot;&amp;gt;{{{图片介绍|}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
! colspan=2 style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}}&amp;quot; | &#039;&#039;&#039;基本资料&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
{{#if:{{{属性1内容|}}}|&lt;br /&gt;
! style=&amp;quot;width:60px&amp;quot; | {{{属性1|}}}&lt;br /&gt;
| {{{属性1内容|}}}&lt;br /&gt;
|-&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性2内容|}}}|&lt;br /&gt;
! {{{属性2|}}}&lt;br /&gt;
| {{{属性2内容|}}}&lt;br /&gt;
|-&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性3内容|}}}|&lt;br /&gt;
! {{{属性3|}}}&lt;br /&gt;
| {{{属性3内容|}}}&lt;br /&gt;
|-&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{额外属性1内容|}}}|&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}};&amp;quot; | &#039;&#039;&#039;{{{额外属性1|}}}&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;&amp;quot; | {{{额外属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
	<entry>
		<id>https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15333</id>
		<title>模板:资料卡片</title>
		<link rel="alternate" type="text/html" href="https://new.pvzhe.wiki/index.php?title=%E6%A8%A1%E6%9D%BF:%E8%B5%84%E6%96%99%E5%8D%A1%E7%89%87&amp;diff=15333"/>
		<updated>2026-07-31T06:48:15Z</updated>

		<summary type="html">&lt;p&gt;愤怒的郎朗：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{| class=&amp;quot;wikitable information&amp;quot; style=&amp;quot;margin: auto;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;padding:0px&amp;quot; | {{#if:{{{图片|}}}|[[file:{{{图片}}}|{{{图片宽度|280px}}}]]}}{{#if:{{{图片介绍|}}}|&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;text-align:center;&amp;quot;&amp;gt;{{{图片介绍|}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
! colspan=2 style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}}&amp;quot; | &#039;&#039;&#039;基本资料&#039;&#039;&#039;&lt;br /&gt;
{{#if:{{{属性1内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:60px&amp;quot; | {{{属性1|}}}&lt;br /&gt;
| {{{属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性2内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性2|}}}&lt;br /&gt;
| {{{属性2内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性3内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性3|}}}&lt;br /&gt;
| {{{属性3内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性4内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性4|}}}&lt;br /&gt;
| {{{属性4内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性5内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性5|}}}&lt;br /&gt;
| {{{属性5内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性6内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性6|}}}&lt;br /&gt;
| {{{属性6内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性7内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性7|}}}&lt;br /&gt;
| {{{属性7内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性8内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性8|}}}&lt;br /&gt;
| {{{属性8内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性9内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性9|}}}&lt;br /&gt;
| {{{属性9内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性10内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性10|}}}&lt;br /&gt;
| {{{属性10内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性11内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性11|}}}&lt;br /&gt;
| {{{属性11内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性12内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性12|}}}&lt;br /&gt;
| {{{属性12内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性13内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性13|}}}&lt;br /&gt;
| {{{属性13内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性14内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性14|}}}&lt;br /&gt;
| {{{属性14内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性15内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性15|}}}&lt;br /&gt;
| {{{属性15内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性16内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性16|}}}&lt;br /&gt;
| {{{属性16内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性17内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性17|}}}&lt;br /&gt;
| {{{属性17内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性18内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性18|}}}&lt;br /&gt;
| {{{属性18内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性19内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性19|}}}&lt;br /&gt;
| {{{属性19内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{属性20内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! {{{属性20|}}}&lt;br /&gt;
| {{{属性20内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if:{{{额外属性1内容|}}}|&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:{{{标题栏颜色|#aaa}}};&amp;quot; | &#039;&#039;&#039;{{{额外属性1|}}}&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;&amp;quot; | {{{额外属性1内容|}}}&lt;br /&gt;
}}&lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{面包屑|模板}}{{模板说明}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>愤怒的郎朗</name></author>
	</entry>
</feed>