<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>学习笔记 on LiaoKe的个人博客</title>
        <link>https://blog.liao-ke.com/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</link>
        <description>Recent content in 学习笔记 on LiaoKe的个人博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Fri, 24 Jul 2026 10:14:30 +0800</lastBuildDate><atom:link href="https://blog.liao-ke.com/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>学习笔记 | 头歌破解考试的防复制粘贴</title>
            <link>https://blog.liao-ke.com/p/educoder-anti-copy-paste-bypass/</link>
            <pubDate>Thu, 23 Jul 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/educoder-anti-copy-paste-bypass/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;有段时间被头歌的防复制粘贴搞得挺头痛的。网上能搜到的脚本，基本只能用于作业的防复制粘贴，到了考试就不行了。于是乎趁着一场模拟考试，研究了一下考试的防复制粘贴机制，最后成功写出来了用于考试的破解的油猴脚本(脚本的完整文件在博客末尾)。&lt;/p&gt;&#xA;&lt;h2 id=&#34;作业场景限制只在配置层面&#34;&gt;作业场景：限制只在&amp;quot;配置层面&amp;quot;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;作业页面的复制限制，本质上只是后端下发的一份&amp;quot;权限配置&amp;quot;&lt;/strong&gt;，前端页面读到这份配置后，才决定要不要在界面上禁用复制粘贴、右键菜单这些功能。限制并不是靠浏览器事件层面的硬拦截实现的，而是看配置文件——配置说不能复制，页面才会去阻止你。&lt;/p&gt;&#xA;&lt;p&gt;这种实现方式的好处是开发简单，但坏处也很明显：只要能在配置到达页面&lt;strong&gt;之前&lt;/strong&gt;把它篡改掉，页面自然就会&amp;quot;以为&amp;quot;自己是被允许复制的，后面所有的限制逻辑都不会触发。&lt;/p&gt;&#xA;&lt;p&gt;所以作业脚本的思路就非常直接：拦截页面发出的所有网络请求，找到返回题目/实训配置的那几个接口，把里面跟复制权限相关的字段统一改成&amp;quot;允许&amp;quot;，再把改过的响应交还给页面。整个过程页面完全无感，因为它拿到的还是一份合法的 JSON，只是内容被偷偷换了。&lt;/p&gt;&#xA;&lt;p&gt;具体做法是重写全局的 &lt;code&gt;fetch&lt;/code&gt;，在真正请求发出后、页面拿到响应前insert一层处理：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hookFetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;nativeFetch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hookedFetch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;nativeFetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;clonedResponse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;clone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;saveTaskJson&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;clonedResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;modifiedResponse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;modifyTaskCopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;clonedResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;modifiedResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hookedFetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;把 &lt;code&gt;shixun&lt;/code&gt;（实训）和 &lt;code&gt;challenge&lt;/code&gt;（题目）对象里那些 &lt;code&gt;forbid_copy&lt;/code&gt;、&lt;code&gt;can_copy&lt;/code&gt;、&lt;code&gt;diasble_copy&lt;/code&gt;之类的字段，全部改写成允许复制的状态：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shixun&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shixun&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;can_copy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shixun&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;forbid_copy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shixun&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;copy_for_exercise&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shixun&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;active_copy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;challenge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;challenge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;diasble_copy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;因为限制只存在于配置层面，所以我们只需要在配置被页面消费之前拦截并篡改它，就能解除限制，不需要碰任何浏览器原生的复制、粘贴、选中事件。&lt;/p&gt;&#xA;&lt;h2 id=&#34;考试场景事件层面的硬拦截&#34;&gt;考试场景：事件层面的硬拦截&#xA;&lt;/h2&gt;&lt;p&gt;但是头歌的考试模式更为复杂。考试系统显然是在作业限制被人破解过太多次之后专门加固的，它不再只依赖一份后端配置——&lt;strong&gt;即便你把配置改成&amp;quot;允许复制&amp;quot;，考试页面依然会在浏览器事件层面把 &lt;code&gt;copy&lt;/code&gt;、&lt;code&gt;cut&lt;/code&gt;、&lt;code&gt;paste&lt;/code&gt;、&lt;code&gt;contextmenu&lt;/code&gt; 这些事件死死摁住&lt;/strong&gt;。同时还配合了 CSS 的 &lt;code&gt;user-select: none&lt;/code&gt; 让你连文字都选不中，甚至连 &lt;code&gt;document.queryCommandSupported(&#39;paste&#39;)&lt;/code&gt; 这种底层探测接口的返回值也被动了手脚。也就是说，考试限制是&amp;quot;多层设防&amp;quot;的：配置层、CSS 选中层、DOM 事件层，缺一不可。&lt;/p&gt;&#xA;&lt;p&gt;这就意味着单纯改配置字段是没有用的——页面的编辑器（Monaco Editor）内部有自己的一套事件监听逻辑，考试脚本会在事件冒泡的过程中调用 &lt;code&gt;preventDefault&lt;/code&gt;、&lt;code&gt;stopPropagation&lt;/code&gt;、&lt;code&gt;stopImmediatePropagation&lt;/code&gt;，把复制粘贴事件在到达 Monaco 自己的处理逻辑之前就地&amp;quot;截杀&amp;quot;。所以要破解考试，思路必须从&amp;quot;改数据&amp;quot;转向&amp;quot;改浏览器事件系统本身的行为&amp;quot;：既然网站是靠调用这几个事件方法来实现拦截的，那就在这几个方法上做手脚，让&amp;quot;调用了但没有真正生效&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;具体做法是直接重写 &lt;code&gt;Event.prototype&lt;/code&gt; 上的三个方法，对来自 Monaco 编辑器内部的复制/剪切/粘贴/右键事件做&amp;quot;选择性失效&amp;quot;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;preventDefault&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;copy&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cut&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 中和网站对 copy/cut 的阻止&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origPreventDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopPropagation&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;paste&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;contextmenu&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;copy&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cut&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 放行，让事件能继续传播给 Monaco 的正常处理逻辑&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origStopPropagation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;这里有个很细节但很关键的取舍：为什么 &lt;code&gt;paste&lt;/code&gt; 和 &lt;code&gt;contextmenu&lt;/code&gt; 的 &lt;code&gt;preventDefault&lt;/code&gt; 要原样保留，只中和 &lt;code&gt;copy&lt;/code&gt;/&lt;code&gt;cut&lt;/code&gt;？因为 Monaco 的右键菜单是它自己用 JS 画出来的浮层，并不是浏览器原生右键菜单；如果把网站对 &lt;code&gt;contextmenu&lt;/code&gt; 的 &lt;code&gt;preventDefault&lt;/code&gt; 也中和掉，浏览器原生菜单和 Monaco 自己的菜单就会同时弹出来，造成&amp;quot;双重菜单&amp;quot;的问题。同理，&lt;code&gt;paste&lt;/code&gt; 事件如果被完全放行，浏览器会执行一次&amp;quot;裸粘贴&amp;quot;，把内容直接怼进 &lt;code&gt;textarea&lt;/code&gt;，绕过了 Monaco 自身的格式化粘贴逻辑，导致粘贴进去的代码缩进全部错乱。所以这两个事件只中和网站的 &lt;code&gt;stopPropagation&lt;/code&gt;（让事件能传到 Monaco 手上），但保留网站对浏览器默认行为的 &lt;code&gt;preventDefault&lt;/code&gt;（把决定权交还给 Monaco 自己）。&lt;/p&gt;&#xA;&lt;p&gt;除此之外，脚本还补了两个容易被忽略的口子：一是给整个页面强制注入 CSS，把 Monaco 编辑器相关节点的 &lt;code&gt;user-select&lt;/code&gt; 都改回 &lt;code&gt;text&lt;/code&gt;，解决&amp;quot;事件放行了但文字根本选不中&amp;quot;的问题；二是遍历并监听页面里动态插入的 &lt;code&gt;iframe&lt;/code&gt;，因为考试页面的编辑器很可能是内嵌在 iframe 里加载的，如果只处理主文档，iframe 内部的限制会完全不受影响：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;handleIframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentDocument&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentWindow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;injectCSS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;patchQCS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;constructor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* 跨域 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;总结&#34;&gt;总结&#xA;&lt;/h2&gt;&lt;p&gt;作业和考试的防复制粘贴的实现思路完全不一样：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;作业&lt;/strong&gt;：限制信息完全来自后端下发的配置字段。破解只需要在数据到达页面前把配置篡改成&amp;quot;允许&amp;quot;，一次 &lt;code&gt;fetch&lt;/code&gt; hook 就能解决所有问题。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;考试&lt;/strong&gt;：在配置层之上又叠了一层针对 DOM 事件的硬编码拦截（&lt;code&gt;copy&lt;/code&gt;/&lt;code&gt;cut&lt;/code&gt;/&lt;code&gt;paste&lt;/code&gt;/&lt;code&gt;contextmenu&lt;/code&gt;），外加 CSS 选中限制和 iframe 隔离。这时候光改数据没用，必须深入到浏览器事件系统本身，精确地区分&amp;quot;网站到底想阻止浏览器的默认行为，还是想阻止事件冒泡到别的处理器&amp;quot;，才能在解除限制的同时不破坏编辑器自身正常的复制粘贴功能。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;最后完整的头歌考试破解防复制粘贴的油猴脚本如下（脚本仅用于技术交流，禁止用于任何非法途径）&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;102&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;103&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;104&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;105&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;106&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;107&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;108&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;109&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;110&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;111&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;112&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;113&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;114&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;115&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;116&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;117&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;118&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;119&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;120&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;121&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;122&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;123&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;124&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;125&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;126&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;127&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;128&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;129&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;130&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;131&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;132&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;133&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;134&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;135&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;136&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;137&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;138&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;139&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;140&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;141&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;142&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;143&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;144&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;145&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;146&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;147&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;148&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;149&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;150&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;151&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;152&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;153&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;154&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;155&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;156&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;157&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;158&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;159&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;160&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;161&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;162&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;163&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;164&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;165&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;166&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;167&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;168&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;169&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;170&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;171&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;172&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;173&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;174&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;175&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;176&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;177&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// ==UserScript==&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @name         头歌平台 (EduCoder) 解除复制粘贴限制&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @namespace    https://github.com/example/educoder-unlocker&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @version      3.0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @description  解除头歌平台代码编辑器的复制粘贴限制（修复右键双重菜单）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @author       AI Assistant&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @match        https://www.educoder.net/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @run-at       document-start&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// @grant        GM_log&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// ==/UserScript==&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;use strict&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;TAG&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;[EduCoder-Unlocker]&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;GM_log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;TAG&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* noop */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;TAG&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;v3.0.1 启动&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// Tools&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;el&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;el&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;el&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;closest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;el&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;closest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.monaco-editor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origPreventDefault&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;preventDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origStopPropagation&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopPropagation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origStopImmediate&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopImmediatePropagation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;preventDefault&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;copy&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cut&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origPreventDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopPropagation&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;paste&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;contextmenu&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;copy&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cut&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origStopPropagation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;Event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopImmediatePropagation&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;paste&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;contextmenu&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;copy&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cut&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_origStopImmediate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;✓ 三件套补丁已生效&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;  preventDefault:   copy/cut → 中和  |  paste/contextmenu → 保留原始&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;  stopPropagation:  全部中和&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;  stopImmediate:    全部中和&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// paste 兜底&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addEventListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;paste&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;insideMonaco&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;preventDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;✓ paste 兜底拦截器已注册&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// CSS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;UNLOCK_CSS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    /* [EduCoder-Unlocker] 恢复 Monaco 编辑器文本选择 */&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .monaco-scrollable-element,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .view-lines,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .view-lines .view-line,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .view-lines *,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .lines-content,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .view-overlays,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .view-overlays .current-line,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .margin-view-overlays,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .line-numbers,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    .monaco-editor .margin .line-numbers {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      -webkit-user-select: text !important;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      -moz-user-select: text !important;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      -ms-user-select: text !important;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      user-select: text !important;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;injectCSS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getElementById&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;educoder-unlocker-css&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;createElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;style&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;educoder-unlocker-css&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;textContent&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;UNLOCK_CSS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;appendChild&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;✓ CSS 注入: &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;主文档&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;iframe&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// queryCommandSupported&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;patchQCS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;docProto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;docProto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;__unlocker_qcs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;orig&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;docProto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryCommandSupported&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;docProto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryCommandSupported&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;cmd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;paste&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;orig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;docProto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;__unlocker_qcs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;patchQCS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// iframe 支持&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ═══════════════════════════════════════════════════════════&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;handleIframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentDocument&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;contentWindow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;doInject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readyState&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;complete&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readyState&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;interactive&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nx&#34;&gt;setTimeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doInject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nx&#34;&gt;injectCSS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nx&#34;&gt;patchQCS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;constructor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prototype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;doInject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* 跨域 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;scanIframes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;iframe&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;forEach&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;handleIframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;mo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;MutationObserver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mutations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;mutations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addedNodes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tagName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;IFRAME&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;handleIframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;iframe&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;forEach&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;handleIframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onDOMReady&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;scanIframes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;mo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;observe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;documentElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;childList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;subtree&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readyState&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;loading&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addEventListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;DOMContentLoaded&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onDOMReady&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;onDOMReady&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;injectCSS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;✓ v3.0.1 就绪 — 文本选择 | 复制 | 粘贴(格式正确) | 剪切 | 右键菜单(仅 Monoco)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;</description>
        </item><item>
            <title>学习笔记 | 一次网页端逆向到 OpenAI 接口封装的完整过程</title>
            <link>https://blog.liao-ke.com/p/orchids-openai-proxy/</link>
            <pubDate>Tue, 21 Jul 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/orchids-openai-proxy/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;最近看到 &lt;a class=&#34;link&#34; href=&#34;https://www.orchids.app&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Orchids&lt;/a&gt; 给了免费的 Claude 和 GPT 额度，但它只提供网页端，没有开放后端 API。&lt;br&gt;&#xA;我就做了一个小实验：不去改它服务端，只复用网页端已有调用链路，把能力封装成一个 &lt;strong&gt;OpenAI API 兼容网关&lt;/strong&gt;，方便接入各类客户端和工具链。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;154px&#34; data-flex-grow=&#34;64&#34; height=&#34;327&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/orchids-openai-proxy/1.png&#34; width=&#34;210&#34;&gt;&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;645px&#34; data-flex-grow=&#34;268&#34; height=&#34;109&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/orchids-openai-proxy/2.png&#34; width=&#34;293&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;这个方案可以跑通，支持流式、思考模式和文件上传，但并不适合做高并发号池，额度和速率都受原平台会话机制限制。本文主要是技术复盘与工程总结。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;一协议适配&#34;&gt;一、协议适配&#xA;&lt;/h2&gt;&lt;p&gt;这次的目标很明确：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;复用网页端已有会话与鉴权流程&lt;/li&gt;&#xA;&lt;li&gt;把上游 SSE 数据流转换成标准 OpenAI 返回结构&lt;/li&gt;&#xA;&lt;li&gt;对外暴露常见 OpenAI 接口，做到低改造接入&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;最终本地服务提供了这些路由：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;GET /health&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;GET /v1/models&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;POST /v1/chat/completions&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;POST /v1/responses&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;POST /v1/files&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;GET /v1/files&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;GET /v1/files/{file_id}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;GET /v1/files/{file_id}/content&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;GET /v1/files/{file_id}/url&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;DELETE /v1/files/{file_id}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;二链路分析从网页请求里抽象最小参数集&#34;&gt;二、链路分析：从网页请求里抽象最小参数集&#xA;&lt;/h2&gt;&lt;p&gt;在网页端实际请求里，可以定位到这几个关键参数：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;clerk_active_context&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;projectId&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;userId&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;__client&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;其中：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;projectId&lt;/code&gt; 来自对话创建后的项目上下文&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;clerk_active_context&lt;/code&gt; 与 &lt;code&gt;__client&lt;/code&gt; 用于会话鉴权&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;userId&lt;/code&gt; 用于拼接上游请求体&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这四个参数就是整个中转服务的最小可用配置。程序启动时交互输入，避免硬编码到源码里。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;500px&#34; data-flex-grow=&#34;208&#34; height=&#34;496&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/orchids-openai-proxy/3.png&#34; srcset=&#34;https://blog.liao-ke.com/p/orchids-openai-proxy/3_hu_f1277f4b6f0e3920.png 800w, https://blog.liao-ke.com/p/orchids-openai-proxy/3.png 1035w&#34; width=&#34;1035&#34;&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;三程序架构&#34;&gt;三、程序架构&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-配置与服务启动&#34;&gt;1) 配置与服务启动&#xA;&lt;/h3&gt;&lt;p&gt;服务启动后读取配置并初始化两个 HTTP Client：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;jwtClient&lt;/code&gt;：用于向 Clerk 换取 JWT&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;upstreamClient&lt;/code&gt;：用于请求 Orchids 的 &lt;code&gt;stream-run&lt;/code&gt; SSE 接口&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;同时挂载 OpenAI 风格路由，作为统一入口。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-鉴权流程&#34;&gt;2) 鉴权流程&#xA;&lt;/h3&gt;&lt;p&gt;核心流程是：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;调用 Clerk token 接口（带 &lt;code&gt;__client&lt;/code&gt; Cookie）&lt;/li&gt;&#xA;&lt;li&gt;获取临时 JWT&lt;/li&gt;&#xA;&lt;li&gt;用 JWT 访问上游推理 SSE&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;也就是说，本地网关没有伪造新鉴权体系，而是复用了网页端已有会话链路。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-上游请求与容错&#34;&gt;3) 上游请求与容错&#xA;&lt;/h3&gt;&lt;p&gt;上游请求采用以下策略：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Authorization: Bearer &amp;lt;jwt&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Accept: text/event-stream&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;网络可重试错误自动重试一次&lt;/li&gt;&#xA;&lt;li&gt;失败时返回清晰错误（包含状态码与上游响应）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这块是工程稳定性的关键，不然很容易因为临时网络抖动导致误判不可用。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;四协议转换把-orchids-sse-映射成-openai-语义&#34;&gt;四、协议转换：把 Orchids SSE 映射成 OpenAI 语义&#xA;&lt;/h2&gt;&lt;p&gt;上游事件流里主要有三类信息：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;文本增量（&lt;code&gt;text_delta&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;思考增量（&lt;code&gt;thinking_delta&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;最终结果与 usage&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;程序分两套解析逻辑：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;parseOrchidsSSEForFinalResult&lt;/code&gt;：非流式聚合&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;parseOrchidsSSEStream&lt;/code&gt;：流式逐段回传&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;再映射为：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Chat Completions：&lt;code&gt;chat.completion&lt;/code&gt; / &lt;code&gt;chat.completion.chunk&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Responses API：&lt;code&gt;response.output_text.delta&lt;/code&gt; / &lt;code&gt;response.completed&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;并且 reasoning 开关打开时，会把 thinking 内容透传到对应字段，保证“思考模式”可用。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;五文件能力兼容-openai-files-接口&#34;&gt;五、文件能力：兼容 OpenAI Files 接口&#xA;&lt;/h2&gt;&lt;p&gt;除了聊天接口，程序还实现了文件链路：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;POST /v1/files&lt;/code&gt; 接收 multipart 文件上传&lt;/li&gt;&#xA;&lt;li&gt;本地落盘并生成 &lt;code&gt;file-xxxx&lt;/code&gt; 形式的 file_id&lt;/li&gt;&#xA;&lt;li&gt;在消息输入中提取 &lt;code&gt;input_file&lt;/code&gt; 的 &lt;code&gt;file_id&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;映射为上游可访问的 &lt;code&gt;attachmentUrls&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;这意味着可以兼容部分依赖 Files API 的客户端工作流，而不只是纯文本对话。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;六支持模型&#34;&gt;六、支持模型&#xA;&lt;/h2&gt;&lt;p&gt;当前版本内置模型列表如下：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;claude-sonnet-4-6&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gpt-5.4&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gpt-5.3-codex&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;claude-opus-4.6&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;claude-opus-4.5&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gpt-5.2-codex&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gpt-5.2&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gemini-3-flash&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gemini-3-pro&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gemini-3.1-pro&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;可通过 &lt;code&gt;GET /v1/models&lt;/code&gt; 查询。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;七实际体验与边界&#34;&gt;七、实际体验与边界&#xA;&lt;/h2&gt;&lt;p&gt;这个方案的优点：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;对接现有 OpenAI 生态方便&lt;/li&gt;&#xA;&lt;li&gt;协议统一后可被多数工具直接消费&lt;/li&gt;&#xA;&lt;li&gt;流式和 reasoning 都可跑通&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;但边界也很明显：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;依赖网页会话参数，稳定性受平台变更影响&lt;/li&gt;&#xA;&lt;li&gt;额度和速度都不适合当号池&lt;/li&gt;&#xA;&lt;li&gt;上游接口一旦改字段，网关要同步维护&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;所以它更适合作为逆向与协议适配实践，而不是生产级高可用方案。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;总结&#xA;&lt;/h2&gt;&lt;p&gt;其实本质上是：&lt;br&gt;&#xA;&lt;strong&gt;把“网页端调用流程”重构成“标准 API 服务”。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;从工程角度看，真正有价值的是：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;能否抽象出最小参数集&lt;/li&gt;&#xA;&lt;li&gt;能否稳定解析 SSE 并保持语义一致&lt;/li&gt;&#xA;&lt;li&gt;能否用统一接口服务不同客户端&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;如果只是临时脚本，那是一次调用；&lt;br&gt;&#xA;完成了协议映射、错误模型和流式对齐，才算一个可复用的接口封装方案。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;程序下载链接：&lt;br&gt;&#xA;&lt;a class=&#34;link&#34; href=&#34;https://www.123865.com/s/vxarVv-o7yHH&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://www.123865.com/s/vxarVv-o7yHH&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;仅用于学习逆向、协议理解和网关设计；&lt;br&gt;&#xA;如果想直接拿来做业务化池子，建议降低预期。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>学习笔记 | 最简单的绕过校园网多设备热点检测方案</title>
            <link>https://blog.liao-ke.com/p/bypass-campus-wifi/</link>
            <pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/bypass-campus-wifi/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;弄到了一个白嫖的校园网账号,但是触发设备连接上限了(电脑只要开热点，wifi就无法访问互联网),我手机电脑无法同时连接,于是便有了接下来这篇教程&lt;/p&gt;&#xA;&lt;h2 id=&#34;原因解析&#34;&gt;原因解析&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;当电脑连接WIFI的时候,网络适配器中的wlan网卡便是已连接的状态&lt;/li&gt;&#xA;&lt;li&gt;此时我们打开热点,在网络适配器中会自动创建一个新的本地连接的网卡&lt;/li&gt;&#xA;&lt;li&gt;在默认情况下,热点的网卡会自动寻找可以访问互联网的网卡，作为上级网卡.&lt;/li&gt;&#xA;&lt;li&gt;但是由于校园网有检测,当热点网卡的流量转发到wlan时,校园网就会检测到有多个设备，从而断开访问&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;596px&#34; data-flex-grow=&#34;248&#34; height=&#34;1021&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/1.png&#34; srcset=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/1_hu_f6ddd3897d7c4762.png 800w, https://blog.liao-ke.com/p/bypass-campus-wifi/1_hu_7766e7470a6c5736.png 1600w, https://blog.liao-ke.com/p/bypass-campus-wifi/1_hu_c9c8b2088f654b12.png 2400w, https://blog.liao-ke.com/p/bypass-campus-wifi/1.png 2536w&#34; width=&#34;2536&#34;&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;解决方法&#34;&gt;解决方法&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;通过手动设置热点网卡的上级网卡到其他的网卡,然后其他网卡的流量(经过这个网卡，对流量进行处理)再流入wlan,这样便不会被校园网检测.&lt;/li&gt;&#xA;&lt;li&gt;于是我们便要用到clash/singbox这样的代理工具的tun模式创造另外一个网卡(其实也可以用wintun驱动手动创建,不过得手动配置一些东西，比较麻烦)&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;398px&#34; data-flex-grow=&#34;165&#34; height=&#34;1522&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/4.png&#34; srcset=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/4_hu_9c14e63979693ea3.png 800w, https://blog.liao-ke.com/p/bypass-campus-wifi/4_hu_cf267a449f2e693b.png 1600w, https://blog.liao-ke.com/p/bypass-campus-wifi/4_hu_4735dd398f200177.png 2400w, https://blog.liao-ke.com/p/bypass-campus-wifi/4.png 2524w&#34; width=&#34;2524&#34;&gt;&lt;/li&gt;&#xA;&lt;li&gt;不一定需要添加clash的代理配置文件,只要打开tun模式即可.&lt;/li&gt;&#xA;&lt;li&gt;此时网络适配器中将会多出一张其他的网络设备&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;475px&#34; data-flex-grow=&#34;198&#34; height=&#34;1279&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/2.png&#34; srcset=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/2_hu_e7e0e595dbb775f3.png 800w, https://blog.liao-ke.com/p/bypass-campus-wifi/2_hu_b84d6fffccdec549.png 1600w, https://blog.liao-ke.com/p/bypass-campus-wifi/2_hu_24c108a4e474ac75.png 2400w, https://blog.liao-ke.com/p/bypass-campus-wifi/2.png 2536w&#34; width=&#34;2536&#34;&gt;&lt;/li&gt;&#xA;&lt;li&gt;此时右击该网卡属性点击共享，然后设置共享的网络为本地连接(相当手动指定热点的上级网络),便可以实现绕过校园网检测&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;420px&#34; data-flex-grow=&#34;175&#34; height=&#34;1455&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/3.png&#34; srcset=&#34;https://blog.liao-ke.com/p/bypass-campus-wifi/3_hu_a56ff396293e3540.png 800w, https://blog.liao-ke.com/p/bypass-campus-wifi/3_hu_bc91273d69530b0b.png 1600w, https://blog.liao-ke.com/p/bypass-campus-wifi/3_hu_4928c0912892392d.png 2400w, https://blog.liao-ke.com/p/bypass-campus-wifi/3.png 2548w&#34; width=&#34;2548&#34;&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>学习笔记 | openwrt25.10设置vlan实现单线复用</title>
            <link>https://blog.liao-ke.com/p/openwrt-vlan/</link>
            <pubDate>Wed, 25 Feb 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/openwrt-vlan/</guid>
            <description>&lt;h2 id=&#34;原理解析&#34;&gt;原理解析&#xA;&lt;/h2&gt;&lt;p&gt;(特别注意:有一些路由器的系统是不支持设置vlanid的,所以建议所有路由器都为openwrt软路由，方便操作.)&lt;/p&gt;&#xA;&lt;p&gt;在传统方案中,当光猫设置&lt;strong&gt;桥接模式&lt;/strong&gt;,软路由负责拨号,此时光猫的其他网口在正常情况下是无法工作的,因为光猫此时只做光电转换，不做路由ip下发.&lt;/p&gt;&#xA;&lt;p&gt;此时我们便需要用到一项技术实现光猫在桥接模式下光猫的其他网口也能正常工作.这便是&lt;strong&gt;vlanid&lt;/strong&gt;.vlanid并不只有&lt;strong&gt;单线复用&lt;/strong&gt;这一个功能,它也可以用来划分局域网,从本质上来讲，它的作用就是给流量打上标记.&lt;/p&gt;&#xA;&lt;p&gt;当光猫桥接主路由拨号时,其他房间网口的流量是流向光猫的网口,在流量没有打&lt;strong&gt;vlanid&lt;/strong&gt;标识的情况下，光猫也不知道要把这些流量弄到哪里去,所以光猫其他网口便无法正常通讯.&lt;/p&gt;&#xA;&lt;p&gt;所以这个时候我们便用&lt;strong&gt;vlanid&lt;/strong&gt;来实现&lt;strong&gt;单线复用&lt;/strong&gt;(&lt;strong&gt;即一条网线，负责实现两个功能,也就是说我们主路由与光猫连接的那根网线既负责主路由的拨号，又负责主路由dhcp服务器下发ip到光猫的其他网口&lt;/strong&gt;),我们在其他网口的房间里的路由器里面设置&lt;strong&gt;vlanid&lt;/strong&gt;,然后在光猫的管理员后台里也设置的&lt;strong&gt;vlanid&lt;/strong&gt;,最后在主路由里面设置一样的&lt;strong&gt;vlanid&lt;/strong&gt;.就这样在三台设备中都设置了&lt;strong&gt;vlanid&lt;/strong&gt;,设备就知道这些流量该如何传输.&lt;/p&gt;&#xA;&lt;h2 id=&#34;具体操作&#34;&gt;具体操作&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;在房间的子路由中把&lt;strong&gt;wan接口删除&lt;/strong&gt;,只留lan口,然后在设备中添加连接网线的网口的vlan设备,然后把这个设备添加到&lt;strong&gt;br-lan&lt;/strong&gt;的网桥设备集合之中&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;577px&#34; data-flex-grow=&#34;240&#34; height=&#34;991&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/1.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/1_hu_bed4ace6e307d14.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/1_hu_af2ca4f3c1b49335.jpg 1600w, https://blog.liao-ke.com/p/openwrt-vlan/1.jpg 2383w&#34; width=&#34;2383&#34;&gt;&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;442px&#34; data-flex-grow=&#34;184&#34; height=&#34;1236&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/2.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/2_hu_e1ca0916ec0c1173.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/2_hu_54e74809fd24f41e.jpg 1600w, https://blog.liao-ke.com/p/openwrt-vlan/2.jpg 2281w&#34; width=&#34;2281&#34;&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;在光猫的管理员后台(&lt;strong&gt;不同的型号的光猫进入管理员后台的方法不同，有一些甚至进不去管理员后台，这里就不细讲了&lt;/strong&gt;),把对应连接方式的lan口绑定全部取消,然后设置对应网口的&lt;strong&gt;vlanid和vlan绑定&lt;/strong&gt;&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;299px&#34; data-flex-grow=&#34;124&#34; height=&#34;985&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/3.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/3_hu_94ffdac528760fa7.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/3.jpg 1228w&#34; width=&#34;1228&#34;&gt;&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;293px&#34; data-flex-grow=&#34;122&#34; height=&#34;998&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/4.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/4_hu_9c75919e4e3c7f72.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/4.jpg 1219w&#34; width=&#34;1219&#34;&gt;&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;244px&#34; data-flex-grow=&#34;101&#34; height=&#34;1180&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/5.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/5_hu_f4d7f32e6e3872e3.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/5.jpg 1200w&#34; width=&#34;1200&#34;&gt;&#xA;以上这张图中，网络连接二是用于主路由和光猫拨号的，而网络连接五则是用于设置vlanid来实现单线复用的。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;在主路由进行和子路由中一样的操作,只是这一次不用把wan口删除了,把wan口对应的连接端口设置&lt;strong&gt;vlanid&lt;/strong&gt;,然后也一并添加到&lt;strong&gt;br-lan&lt;/strong&gt;中即可完成配置&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;464px&#34; data-flex-grow=&#34;193&#34; height=&#34;1320&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/6.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/6_hu_8fb1fb10e4e9a234.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/6_hu_4cea7f81684e07f7.jpg 1600w, https://blog.liao-ke.com/p/openwrt-vlan/6_hu_db16147587da4ba1.jpg 2400w, https://blog.liao-ke.com/p/openwrt-vlan/6.jpg 2553w&#34; width=&#34;2553&#34;&gt;&#xA;&lt;img class=&#34;gallery-image&#34; data-flex-basis=&#34;453px&#34; data-flex-grow=&#34;188&#34; height=&#34;1351&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.liao-ke.com/p/openwrt-vlan/7.jpg&#34; srcset=&#34;https://blog.liao-ke.com/p/openwrt-vlan/7_hu_c3f838f7acdbb915.jpg 800w, https://blog.liao-ke.com/p/openwrt-vlan/7_hu_81134c7cf31261b1.jpg 1600w, https://blog.liao-ke.com/p/openwrt-vlan/7_hu_8a45356256eca507.jpg 2400w, https://blog.liao-ke.com/p/openwrt-vlan/7.jpg 2553w&#34; width=&#34;2553&#34;&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;完成了以上三个步骤,就可以实现光猫在&lt;strong&gt;桥接模式&lt;/strong&gt;下，房间的子路由仍然可以接收到主路由下发的ip了&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>学习笔记 | Hugo自动修正文章最后修改时间的最佳方案</title>
            <link>https://blog.liao-ke.com/p/hugo-add-lastmod-to-posts/</link>
            <pubDate>Sun, 25 Jan 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/hugo-add-lastmod-to-posts/</guid>
            <description>&lt;h1 id=&#34;hugo-全自动修正文章修改时间的最佳实践serverless-场景&#34;&gt;Hugo 全自动修正文章修改时间的最佳实践（Serverless 场景）&#xA;&lt;/h1&gt;&lt;p&gt;在使用 Hugo 构建静态博客时，&lt;strong&gt;文章的修改时间（Last Modified Time）&lt;/strong&gt; 是一个非常重要但又容易踩坑的问题，尤其是在 &lt;strong&gt;Serverless / CI 自动部署&lt;/strong&gt; 场景下。&lt;/p&gt;&#xA;&lt;p&gt;Hugo 官方目前提供了多种用于确定文章修改时间的方式：&lt;/p&gt;&#xA;&lt;h2 id=&#34;hugo-支持的修改时间来源&#34;&gt;Hugo 支持的修改时间来源&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;:filemodtime&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&#xA;使用文件本身的最后修改时间作为文章的修改时间。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;lastmod&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&#xA;需要在文章 Front Matter 中手动维护 &lt;code&gt;lastmod&lt;/code&gt; 字段。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;:git&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&#xA;使用 Git 中该文件的&lt;strong&gt;最后一次提交时间&lt;/strong&gt;作为修改时间（依赖 &lt;code&gt;gitinfo&lt;/code&gt;）。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;date&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&#xA;使用文章的发布时间作为修改时间。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;各方案的自动化可行性分析&#34;&gt;各方案的自动化可行性分析&#xA;&lt;/h2&gt;&lt;p&gt;在上述方案中：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;✅ &lt;strong&gt;可自动化&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;:filemodtime&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;:git&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;❌ &lt;strong&gt;不适合全自动&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;lastmod&lt;/code&gt;（需要人工维护）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;date&lt;/code&gt;（语义不符）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;filemodtime-在-serverless-场景下的问题&#34;&gt;:filemodtime 在 Serverless 场景下的问题&#xA;&lt;/h2&gt;&lt;p&gt;使用 Hugo 的一个重要原因，正是为了 &lt;strong&gt;方便地将网站部署到 Serverless 平台&lt;/strong&gt;（如 Cloudflare Pages、Vercel、Netlify 等）。&lt;/p&gt;&#xA;&lt;p&gt;然而在 Serverless / CI 场景中：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;每次部署都会重新 &lt;code&gt;git clone&lt;/code&gt; 仓库&lt;/li&gt;&#xA;&lt;li&gt;所有文件的 &lt;strong&gt;文件系统修改时间&lt;/strong&gt; 都会变成「拉取时间」&lt;/li&gt;&#xA;&lt;li&gt;这会导致：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;所有文章的修改时间被错误地更新为“本次部署时间”&lt;/li&gt;&#xA;&lt;li&gt;完全失去文章真实修改时间的意义&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;因此，&lt;strong&gt;&lt;code&gt;:filemodtime&lt;/code&gt; 在默认情况下并不适合 Serverless 场景&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;git-方案的现实问题&#34;&gt;:git 方案的现实问题&#xA;&lt;/h2&gt;&lt;p&gt;理论上，&lt;code&gt;:git&lt;/code&gt; 是最理想的方案：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;修改时间与 Git 提交严格一致&lt;/li&gt;&#xA;&lt;li&gt;完全自动化&lt;/li&gt;&#xA;&lt;li&gt;不依赖文件系统时间戳&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;但在实际使用中：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;即使开启了 &lt;code&gt;enableGitInfo = true&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;某些情况下 &lt;code&gt;:git&lt;/code&gt; &lt;strong&gt;无法正确生效&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;在 CI / Serverless 环境中尤为明显&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;不确定这是环境限制、Git shallow clone、还是 Hugo 本身的 Bug，但结果是：&lt;strong&gt;该方案在实践中不够稳定&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;最终解决方案修改文件时间戳为git-提交时间--filemodtime&#34;&gt;最终解决方案：修改文件时间戳为Git 提交时间 + :filemodtime&#xA;&lt;/h2&gt;&lt;p&gt;综合以上问题，我最终总结出了一套&lt;strong&gt;最适合 Serverless 管理的全自动方案&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;h3 id=&#34;核心思路&#34;&gt;核心思路&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;&lt;strong&gt;在 Hugo 构建之前，将文件的修改时间戳“伪装”为 Git 最后提交时间。&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;具体流程如下：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Hugo 中使用 &lt;code&gt;:filemodtime&lt;/code&gt; 作为文章修改时间来源&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[frontmatter]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lastmod = [&amp;#39;:fileModTime&amp;#39;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;将脚本放在文件夹根目录&lt;/li&gt;&#xA;&lt;li&gt;将自动执行脚本的命令和正式部署命令合二为一(&lt;strong&gt;这里需要注意的是一般的serverless平台拉取项目只是浅层克隆不会把文件的最后提交信息给拉取过来，所以我们要在最前面要执行完整的拉取命令。&lt;/strong&gt;)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git fetch --unshallow &amp;amp;&amp;amp; chmod +x 1.sh &amp;amp;&amp;amp; ./1.sh &amp;amp;&amp;amp; hugo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;Serverless平台设置环境变量TZ为Asia/Shanghai(不然的话，一般Serverless平台默认应该是美国的时间,会影响构建出来的网站的文章的最后修改日期的准确性)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;这样就可以做到：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;✅ 修改时间与 Git 提交时间一致&lt;/li&gt;&#xA;&lt;li&gt;✅ 完全自动化&lt;/li&gt;&#xA;&lt;li&gt;✅ 与 Serverless / CI 环境完美兼容&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;自动同步-git-提交时间到文件修改时间的脚本&#34;&gt;自动同步 Git 提交时间到文件修改时间的脚本&#xA;&lt;/h2&gt;&lt;p&gt;下面的脚本用于：&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;&lt;strong&gt;将当前目录下所有文件的最后修改时间，统一修改为对应的 Git 最后提交时间&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# （此处放置你的脚本内容）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#!/bin/bash&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# git-set-filetime.sh&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 功能：将 git 仓库中所有被追踪文件的修改时间改为最后一次提交时间&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 确保当前目录是 git 仓库&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; ! -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;.git&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Error: 当前目录不是 git 仓库根目录&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 获取所有被追踪文件（包含特殊字符/空格/中文）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git ls-files -z &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;IFS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt; -r -d &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; file&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 获取最后一次提交的 Unix 时间戳&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;timestamp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;git log -1 --format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;%ct&amp;#34;&lt;/span&gt; -- &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$timestamp&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# 使用 touch 修改文件修改时间&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# -d &amp;#34;@$timestamp&amp;#34; 表示从 Unix 时间戳设置时间&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        touch -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;@&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$timestamp&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Updated: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; -&amp;gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;date -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;@&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$timestamp&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;+%Y-%m-%d %H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Skipped (not tracked): &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;All tracked files&amp;#39; modification times updated.&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;</description>
        </item><item>
            <title>学习笔记 | GKI 内核不完全编译实战</title>
            <link>https://blog.liao-ke.com/p/android-gki-kernel-compile/</link>
            <pubDate>Fri, 05 Dec 2025 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/android-gki-kernel-compile/</guid>
            <description>&lt;h2 id=&#34;android内核编译&#34;&gt;Android内核编译&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;以编译5.10以上的内核为例,所需资源:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;一台配置较好的电脑&lt;/li&gt;&#xA;&lt;li&gt;linux系统&lt;/li&gt;&#xA;&lt;li&gt;内核源代码&lt;/li&gt;&#xA;&lt;li&gt;编译链工具&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;linux系统&#34;&gt;linux系统&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;各大Linux系统(Ubuntu系/arch系/fedora系/Wsl2)都可以，网上教程多以Ubuntu lts版本为例(&lt;strong&gt;便于找依赖和教程&lt;/strong&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;内核源代码&#34;&gt;内核源代码&#xA;&lt;/h3&gt;&lt;p&gt;从github上搜索自己机型的内核源代码&lt;br&gt;&#xA;如&lt;code&gt;https://github.com/Evolution-X-Devices/kernel_xiaomi_sm8450&lt;/code&gt;(&lt;strong&gt;项目名一般采用   kernel_厂家名_芯片组代号   的形式,5.10之后都是gki内核,所以内核名称基本是以芯片组命名如sm8450,有些项目也可能是按机型代号命名，而不是芯片组&lt;/strong&gt;)&lt;/p&gt;&#xA;&lt;h3 id=&#34;编译链工具&#34;&gt;编译链工具&#xA;&lt;/h3&gt;&lt;p&gt;5.10以上的内核一般采用纯clang/llvm进行编译(低版本内核也可尝试，但有可能能成功编译但会开不了机)&lt;/p&gt;&#xA;&lt;h4 id=&#34;clangllvm&#34;&gt;Clang/llvm&#xA;&lt;/h4&gt;&lt;p&gt;Clang 一般情况下采用的是&lt;a class=&#34;link&#34; href=&#34;https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86/&amp;#43;/refs/heads/main&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;google&lt;/a&gt;的正式分支,也可以采用&lt;a class=&#34;link&#34; href=&#34;https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86/&amp;#43;/refs/heads/mirror-goog-main-prebuilts&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;测试分支&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;编译过程&#34;&gt;编译过程&#xA;&lt;/h3&gt;&lt;h4 id=&#34;更新环境依赖&#34;&gt;更新环境依赖&#xA;&lt;/h4&gt;&lt;p&gt;以Ubuntu24.04为例,执行以下命令安装依赖&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc tar xz-utils cpio findutils&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h4 id=&#34;克隆内核源代码和编译链工具&#34;&gt;克隆内核源代码和编译链工具&#xA;&lt;/h4&gt;&lt;p&gt;内核:&lt;code&gt;git clone https://github.com/Evolution-X-Devices/kernel_xiaomi_sm8450.git --depth=1&lt;/code&gt;&lt;br&gt;&#xA;编译链工具:&lt;code&gt;git clone https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86.git --depth=1&lt;/code&gt;&lt;br&gt;&#xA;&lt;strong&gt;depth=1&lt;/strong&gt;只拉取文件，不拉取历史提交，可以极大减少下载时间&lt;br&gt;&#xA;如果想拉取其他的测试分支，也可以在后面加&lt;code&gt;-b 测试分支名字&lt;/code&gt;&lt;br&gt;&#xA;如拉取测试版的编译链则添加&lt;code&gt;-b mirror-goog-main-prebuilts&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h4 id=&#34;设置环境变量&#34;&gt;设置环境变量&#xA;&lt;/h4&gt;&lt;p&gt;注:&lt;code&gt;以下操作需要在同一个终端环境下执行，因为添加的变量是临时变量&lt;/code&gt;&lt;br&gt;&#xA;此时在你的工作目录下面应该会有两个文件夹，一是&lt;code&gt;内核文件夹&lt;/code&gt;，二是&lt;code&gt;编译链工具文件夹&lt;/code&gt;&lt;br&gt;&#xA;打开终端,执行&lt;code&gt;cd 编译链工具文件夹路径&lt;/code&gt;,当前目录下应该会有若干个&lt;code&gt;clang-rxxxx&lt;/code&gt;子文件夹，选择后缀数字最大的最新版本即可,将它下面的/bin添加到环境变量中&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:/../../编译链工具文件夹/clang-rxxxx/bin&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;然后再&lt;code&gt;cd 内核源代码文件夹&lt;/code&gt;&lt;br&gt;&#xA;设置编译环境变量&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ARCH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;SUBARCH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;CC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;clang&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;LLVM&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;LLVM_IAS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;HOSTCC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;clang&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;LD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;ld.lld&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;CLANG_TRIPLE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;aarch64-linux-gnu-&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;如果电脑的内存不太够，可以额外设置&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;LTO&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;thin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h4 id=&#34;执行编译命令&#34;&gt;执行编译命令&#xA;&lt;/h4&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make &lt;span class=&#34;nv&#34;&gt;ARCH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt; gki_defconfig&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make -j&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;nproc --all&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;第一行命令是加载配置文件gki_defconfig,他所在的目录是&lt;code&gt;/内核源代码/arch/arm64/configs/gki_defconfig&lt;/code&gt;（可以自行修改里面的配置项）&lt;br&gt;&#xA;编译出来的内核二进制文件会在&lt;code&gt;/内核源代码/arch/arm64/boot/Image&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;打包内核&#34;&gt;打包内核&#xA;&lt;/h3&gt;&lt;p&gt;由于没有编译kernel-devicetree,也没ramdisk,所以无法和内核二进制文件打包成boot.img刷入手机分区(也可以用magiskboot把手机原本的boot.img进行解包，把其中的内核二进制文件替换之后,再打包就行了)&lt;br&gt;&#xA;这个时候就需要&lt;a class=&#34;link&#34; href=&#34;https://github.com/osm0sis/AnyKernel3&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;AnyKernel3&lt;/a&gt;对内核二进制文件进行打包&lt;br&gt;&#xA;详细教程参考&lt;br&gt;&#xA;&lt;a class=&#34;link&#34; href=&#34;https://github.com/tiann/KernelSU/discussions/952&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://github.com/tiann/KernelSU/discussions/952&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;刷入内核&#34;&gt;刷入内核&#xA;&lt;/h3&gt;&lt;p&gt;可以在twrp或一些用于刷写内核的app中刷入打包后的AnyKernel3.zip&lt;/p&gt;&#xA;&lt;h3 id=&#34;注意&#34;&gt;注意&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;不同型号内核以及不同版本的编译器，可能对依赖和代码语法要求也有所不同，需要自行解决。&lt;/strong&gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>学习笔记 | Steam 假入库那些事</title>
            <link>https://blog.liao-ke.com/p/steam-fake-inventory/</link>
            <pubDate>Wed, 03 Dec 2025 00:00:00 +0000</pubDate>
            <guid>https://blog.liao-ke.com/p/steam-fake-inventory/</guid>
            <description>&lt;h2 id=&#34;steam假入库到底是什么&#34;&gt;Steam假入库到底是什么？&#xA;&lt;/h2&gt;&lt;p&gt;淘宝上有很多低价的steam游戏cdk,但购买之后实际是运行脚本入库(有自己steam账号信息泄露的风险),可以在本地游玩.（&lt;strong&gt;换台设备重新登录账号，假入库游戏将会被清空。&lt;/strong&gt;）&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;实际上账号并没有拥有游戏,别人是看不到你的账号拥有该游戏的&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;假入库原理分析&#34;&gt;假入库原理分析:&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Steam购买游戏相当于购买游戏的游玩资格，购买完成后，将会下载游戏的清单文件(相当于下载列表),然后steam会用游戏的depot key(正版购买用户自动下发)对清单文件进行解密下载,下载完成后，打开游戏会调用steamwork api进行验证当前运行的steam账号是否拥有该游戏,认证通过后即可正常游玩。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;我们可以在其中做些手脚,便可以实现假入库。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;游戏清单文件是可以公开找到的，但是需要正版账号的depot key解密才可以解密下载(&lt;strong&gt;游戏每一个版本的清单文件对应着一个depot key,所以想要玩到最新的游戏内容，密钥文件也需要及时更新&lt;/strong&gt;)。假入库的商家可能会根据爬虫或者其他技术手段(如通过木马病毒从其他steam玩家账号中提取depot key)，可以搞到最新的游戏depot key&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;通过解密清单将游戏完整下下来后,通过steamtool/GreenLuma hook注入自己的.dll文件,对steam原有的steamwork api进行劫持,便可以实现让游戏认为账号已经获取了该游戏的游玩权限。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;于是乎通过以上手段，便实现了一套完整的steam游戏假入库&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;在steam游戏破解游玩方面,主要有两种破解方法&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;一是对steam客户端进行crak&#34;&gt;一是对steam客户端进行crak&#xA;&lt;/h3&gt;&lt;p&gt;让steam认为你拥有该游戏的游玩权限,再搭配实时获取别人最新的depot key,便可实现几乎与正版购买一致的游戏体验(云存档,成就系统等等)&lt;/p&gt;&#xA;&lt;h4 id=&#34;弊端&#34;&gt;弊端:&#xA;&lt;/h4&gt;&lt;ol&gt;&#xA;&lt;li&gt;无法使用联机功能&lt;/li&gt;&#xA;&lt;li&gt;别人看不到你库中的游戏(无伤大雅,除非你想要通过玩游戏来证明自己的老资历,在某盒软件舆论战中占上风)&lt;/li&gt;&#xA;&lt;li&gt;系统重装后，steam假入库游戏入库数据会消失(要玩的时候重新入一下库就行了，问题不大)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h4 id=&#34;典型代表&#34;&gt;典型代表:&#xA;&lt;/h4&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.steamtools.net&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;steamtool&lt;/a&gt; (闭源，国人大佬开发,功能强大)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://cs.rin.ru/forum/viewtopic.php?t=103709&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;GreenLuma&lt;/a&gt;(原版纯命令行,操作较难,闭源,外国论坛发布)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/clinlx/CN_GreenLumaGUI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;GreenLuma_CN&lt;/a&gt;(原版加上前端，方便操作)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;二是对游戏文件本身进行修改&#34;&gt;二是对游戏文件本身进行修改&#xA;&lt;/h3&gt;&lt;p&gt;对游戏文件夹本身进行修改,内置一个模仿steam api行为的第三方轻量steam client,实现steam游戏脱离steam官方客户端运行,方便游戏在互联网上传播&lt;/p&gt;&#xA;&lt;h4 id=&#34;弊端-1&#34;&gt;弊端:&#xA;&lt;/h4&gt;&lt;ol&gt;&#xA;&lt;li&gt;不方便游戏新版本的更新和获取&lt;/li&gt;&#xA;&lt;li&gt;无法使用steam官方客户端的一些功能&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h4 id=&#34;典型代表-1&#34;&gt;典型代表:&#xA;&lt;/h4&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Detanup01/gbe_fork&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;gbe_fork&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/SteamAutoCracks/Steam-auto-crack&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;steam-auto-crak&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;其他&#34;&gt;其他:&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;steamlan/gbe 通过模仿steam lan api,可以实现游戏在线/离线模式下局域网联机,而不需要走steam官方服务器&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/atom0s/Steamless&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;steamless&lt;/a&gt; 移除steam端的d加密(不会绕过游戏游玩验证,并且非steam的d加密无法破解，比如说黑猴,需要使用别人的d加密密钥才可以认证游玩)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;总结&#34;&gt;总结:&#xA;&lt;/h3&gt;&lt;p&gt;Steam假入库商家通常通过劫持steam根目录的hid.dll文件进行自定义操作,hook核心一般采用steamtool,加上不知道哪里搞来的清单depot key源,由于是黑箱代码,无法准确判断是否含有其他的木马病毒,来获取自己steam的一些信息,对账号造成隐性风险,所以不建议使用淘宝上的 steam假入库。&lt;/p&gt;&#xA;&lt;h4 id=&#34;辨别方法&#34;&gt;辨别方法:&#xA;&lt;/h4&gt;&lt;p&gt;由于steam假入库这件事已经有一定的知名度了,有些商家也学聪明了，把正版的激活流程放在介绍页，然后下面配一行小字，如果正版激活不行(100%是不成功的)，再采用其他方法(他们自己的脚本).&lt;/p&gt;&#xA;&lt;p&gt;主要由以下两个方法判断:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;cdk价格过低的，100%都是假入库&lt;/li&gt;&#xA;&lt;li&gt;直接询问客服是否可以在手机上通过steam客户端cdk激活（假入库的脚本程序无法在手机上运行）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h4 id=&#34;解除假入库&#34;&gt;解除假入库&#xA;&lt;/h4&gt;&lt;ol&gt;&#xA;&lt;li&gt;使用&lt;a class=&#34;link&#34; href=&#34;https://cloud.ksmlc.cn/home?path=cloudreve%3A%2F%2FPDSB%40share&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;steam解锁文件管理器&lt;/a&gt;删除假入库的游戏&lt;/li&gt;&#xA;&lt;li&gt;&lt;del&gt;然后删除steam根目录的hid.dll&lt;/del&gt;(steam更新64位后,hid.dll劫持的方案已经失效了,换别的方案了)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;strong&gt;最后严肃声明，本文章仅供技术探讨，支持正版从我做起&lt;/strong&gt;&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
