jdjwzx233的博客

<ol> <li></li> <li> <p>如无特别声明,该博客文章均为 jdjwzx233 原创,转载请遵循署名 - 非商业性使用 4.0 国际(CC BY-NC-SA)协议,即转载请注明文章来源。</p> </li> <li> <p><strong>如发现用户发布违规内容或评论,管理员将封禁其 IP 地址!(所有 jdjwzx233 的站点将不可访问。如果有误封,请联系 <a href="mailto:admin@jdjwzx233.cn">admin@jdjwzx233.cn</a> 进行申诉)</strong></p> </li> <li> <p>本博客使用 <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvLw==">hexo</span> 进行搭建,采用 shoka 主题。</p> </li> <li> <p>本博客属于非商业性质的博客。</p> </li> <li> <p>如需联系 jdjwzx233,请<span class="exturl" data-url="aHR0cHM6Ly9hcGkuYnRzdHUuY24vcXF0YWxrL2FwaS5waHA/cXE9MTQzODE0ODI0Mw==">点击这里</span>,或通过添加好友的方式联系 jdjwzx233-bot(QQ: 1438148243)。在进入 QQ 后,向 jdjwzx233-bot 发送指令 &quot;!rg&quot;,即可获取 jdjwzx233 的联系方式。获取好友验证码请参考第 7 条。</p> </li> <li> <p>如果博客文章、使用的图片等侵犯了您的版权或给您带来了损失,请联系 <strong><a href="mailto:admin@jdjwzx233.cn">admin@jdjwzx233.cn</a></strong>。</p> </li> <li> <p>jdjwzx233-bot 的好友验证码为:jdjwzx233blogyyds(不定时更改)。</p> </li> <li> <p>jdjwzx233-bot 将于 2023 年二月份关闭,客服业务已经转移到 jdjwzx233-Blog 上。您现在可以通过博客右下角的咨询按钮联系 jdjwzx233-Blog 的管理员。</p> </li> <li> <p>如果喜欢 jdjwzx233-Blog,请<a href="/Subscribe">点击这里</a>订阅,获取 jdjwzx233-Blog 的最新动态。</p> </li> <li> <p>如果您访问本站,即表示您同意本站的<a href="/Privacy%20policy">隐私政策</a>、<a href="/Cookiepolicy">Cookie 政策</a>、<a href="/Term%20sand%20conditions">服务条款</a>和<a href="/Disclaimer">免责声明</a>。如果您不同意相关政策和条款,请勿访问本站。您可以联系 <strong><a href="mailto:admin@jdjwzx233.cn">admin@jdjwzx233.cn</a></strong> 删除您在本站中的一切信息(包括评论、账户、文章等)。</p> </li> <li> <p>为了尊重和保护访客和用户的隐私权,我们提供了一种方便的方式来关闭网站跟踪器。您可以在网站底部找到相应选项,以便自主选择是否接受网站跟踪。我们鼓励您在使用我们的网站时行使您的选择权,以获得更加个性化和符合您需求的浏览体验。</p> </li> <li> <p>本站点已启用腾讯云 CDN 加速,加速网址:<span class="exturl" data-url="aHR0cDovL3d3dy5qZGp3engyMzMuY24=">www.jdjwzx233.cn</span></p> </li> <li> <p>您可以使用爱发电赞助本博客的运营和开发。</p> </li> <li> <p>赞助感谢名单:<span class="exturl" data-url="aHR0cHM6Ly9zcG9uc29ybWUuamRqd3p4MjMzLmNvbS8=">https://sponsorme.jdjwzx233.com/</span></p> </li> </ol> <p><div class="links"><div class="item" title="jdjwzx233" style="--block-color:#e9546b;"><span class="exturl image" data-url="aHR0cHM6Ly9hZmRpYW4uY29tL3UvY2Q3ZjQ5ZjIwZjRiMTFlZDlmM2M1MjU0MDAyNWMzNzc=" data-background-image="https://upcdn.jdjwzx233.cn/upload/Qexo/24/11/24/logo_0bab5ae4d8eb33ed096e89d0912170f3.png"></span> <div class="info"> <span class="exturl title" data-url="aHR0cHM6Ly9hZmRpYW4uY29tL3UvY2Q3ZjQ5ZjIwZjRiMTFlZDlmM2M1MjU0MDAyNWMzNzc=">爱发电-jdjwzx233</span> <p class="desc">每月5元,感谢您的赞助</p> </div></div></div></p> <p><strong>广告</strong>:</p> <ol> <li><strong>LightNode</strong>:拥有高质量香港 CN2 GIA 节点与原生 IP (河内、曼谷、华盛顿、柬埔寨)。充值 10 美元,最多账户获得 30 美元,10 美元可用 5 个月,相当于<strong>不要钱</strong>。(<strong>支持支付宝、银联、paypal 等支付方式</strong>)。对于想用 VPS 解锁 **「Netflix、 TikTok」** 或者其他流媒体,以及对 CN2 有需求的都可以看看。官网链接:<span class="exturl" data-url="aHR0cHM6Ly93d3cubGlnaHRub2RlLmNvbS8/aW52aXRlQ29kZT1BRFFWTUomYW1wO3Byb21vdGVXYXk9TElOSw==">www.lightnode.com</span></li> <li><strong>又拍云</strong>:又拍云有非常多的优惠:加入又拍云联盟 (网站需备案,要在网站 / 应用底部添加又拍云 LOGO 并指向官网) 后,可以获得每月 10G 储存空间和 15G 的 CDN 流量 (按年发放,以 67 元的代金卷发放到账户);新用户注册 (<span class="exturl" data-url="aHR0cHM6Ly9jb25zb2xlLnVweXVuLmNvbS9yZWdpc3Rlci8/aW52aXRlPXRJOGxqaXhJVA==">点我注册</span>) 还可以直接获得 61 元的代金卷 (有效期一年)。在这些优惠的加成下,你可以零成本建站。</li> </ol> <p><strong><span class="exturl" data-url="aHR0cHM6Ly9jaWFsbG8ubXkv">Ciallo~(∠・ω&lt; )⌒★</span></strong></p>

2026/7/18
阅读更多

网页自动翻译功能全攻略

<h2 id="前言"><a class="anchor" href="#前言">#</a> 前言</h2> <p>在全球化互联网生态中,网站访问者往往来自不同语言背景,语言壁垒成为信息传递的天然障碍。传统多语言方案依赖人工维护静态翻译文件,不仅更新滞后、维护成本高昂,更无法应对动态内容和用户生成数据的实时翻译需求。与此同时,许多开发者陷入两难:直接调用谷歌翻译等公共接口可能面临服务稳定性风险,而私有化部署方案又常因技术复杂度望而却步。</p> <p>为突破这一困局,现代网页自动翻译技术应运而生。它不仅能实现毫秒级动态内容转化,更通过智能术语库和私有接口对接,在提升用户体验与控制翻译质量之间找到平衡点。</p> <h2 id="一-谷歌翻译原生集成方案"><a class="anchor" href="#一-谷歌翻译原生集成方案">#</a> 一、谷歌翻译原生集成方案</h2> <h3 id="1-实现原理"><a class="anchor" href="#1-实现原理">#</a> 1. 实现原理</h3> <p>通过动态加载谷歌翻译的脚本( <code>element.js</code> ),在页面中插入翻译控件,利用 Google 的云端接口实现实时翻译。</p> <h3 id="2-操作步骤"><a class="anchor" href="#2-操作步骤">#</a> 2. 操作步骤</h3> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- index.html 中插入脚本加载逻辑 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="variable language_">window</span>.<span class="property">onload</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> script.<span class="property">src</span> = <span class="string">&#x27;https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> script.<span class="property">onerror</span> = <span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;Google 翻译加载失败,请检查网络环境&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="property">head</span>.<span class="title function_">appendChild</span>(script);</span></span><br><span class="line"><span class="language-javascript">&#125;;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 翻译控件容器 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;google_translate_element&quot;</span> <span class="attr">style</span>=<span class="string">&quot;position:fixed;bottom:20px;right:20px;z-index:999&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></p> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Vue/React 组件中初始化翻译器</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">googleTranslateElementInit</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">new</span> google.<span class="property">translate</span>.<span class="title class_">TranslateElement</span>(&#123;</span><br><span class="line"> <span class="attr">pageLanguage</span>: <span class="string">&#x27;zh-CN&#x27;</span>,</span><br><span class="line"> <span class="attr">includedLanguages</span>: <span class="string">&#x27;en,ja,ko,es&#x27;</span>, <span class="comment">// 限制可切换语言</span></span><br><span class="line"> <span class="attr">layout</span>: google.<span class="property">translate</span>.<span class="property">TranslateElement</span>.<span class="property">InlineLayout</span>.<span class="property">SIMPLE</span></span><br><span class="line"> &#125;, <span class="string">&#x27;google_translate_element&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p> <p><strong>注意事项</strong>:需科学上网环境支持,频繁调用可能触发接口限制。</p> <hr /> <h2 id="二-使用i18n-jsautotranslate-库"><a class="anchor" href="#二-使用i18n-jsautotranslate-库">#</a> 二、使用 i18n-jsautotranslate 库</h2> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js 全局配置</span></span><br><span class="line"><span class="keyword">import</span> translate <span class="keyword">from</span> <span class="string">&#x27;i18n-jsautotranslate&#x27;</span>;</span><br><span class="line">translate.<span class="property">listener</span>.<span class="title function_">start</span>(); <span class="comment">// 监控动态文本</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$translate</span> = translate;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 组件内切换语言</span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">$translate</span>.<span class="title function_">changeLanguage</span>(<span class="string">&#x27;english&#x27;</span>);</span><br><span class="line"><span class="variable language_">this</span>.<span class="property">$translate</span>.<span class="title function_">execute</span>(); <span class="comment">// 强制刷新翻译</span></span><br></pre></td></tr></table></figure></p> <p><strong>特点</strong>:轻量级集成,但需手动处理接口返回的动态内容。</p> <h2 id="三-使用translatejs实现此处为简略内容详细的看最后面"><a class="anchor" href="#三-使用translatejs实现此处为简略内容详细的看最后面">#</a> 三、使用 translate.js 实现 (此处为简略内容,详细的看最后面)</h2> <p><strong>使用 GitHub 项目:<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL3hueDMvdHJhbnNsYXRl">translate</span>,如果你觉得这个项目好的话,可以去给项目点个 star</strong></p> <h3 id="31-基础集成"><a class="anchor" href="#31-基础集成">#</a> 3.1 基础集成</h3> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 引入核心库 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.staticfile.net/translate.js/3.12.0/translate.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 自定义语言切换按钮 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;lang-switcher&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">&quot;translate.changeLanguage(&#x27;english&#x27;)&quot;</span>&gt;</span>English<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">&quot;translate.changeLanguage(&#x27;chinese_simplified&#x27;)&quot;</span>&gt;</span>简体中文<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="comment">// 初始化配置</span></span></span><br><span class="line"><span class="language-javascript">translate.<span class="property">language</span>.<span class="title function_">setLocal</span>(<span class="string">&#x27;chinese_simplified&#x27;</span>); <span class="comment">// 设置源语言</span></span></span><br><span class="line"><span class="language-javascript">translate.<span class="property">service</span>.<span class="title function_">use</span>(<span class="string">&#x27;client.edge&#x27;</span>); <span class="comment">// 使用边缘计算翻译通道</span></span></span><br><span class="line"><span class="language-javascript">translate.<span class="title function_">execute</span>(); <span class="comment">// 立即执行翻译</span></span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></p> <h3 id="32-核心功能详解"><a class="anchor" href="#32-核心功能详解">#</a> 3.2 核心功能详解</h3> <h4 id="1动态内容监控"><a class="anchor" href="#1动态内容监控">#</a> (1)动态内容监控</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">translate.<span class="property">listener</span>.<span class="title function_">start</span>(); <span class="comment">// 开启DOM变动监听</span></span><br><span class="line">translate.<span class="property">ignore</span>.<span class="property">class</span>.<span class="title function_">push</span>(<span class="string">&#x27;no-translate&#x27;</span>); <span class="comment">// 忽略特定class</span></span><br></pre></td></tr></table></figure></p> <p><strong>应用场景</strong>:Vue/React 等框架的动态渲染内容自动翻译。</p> <h4 id="2自定义术语库"><a class="anchor" href="#2自定义术语库">#</a> (2)自定义术语库</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">translate.<span class="property">term</span>.<span class="title function_">set</span>(&#123;</span><br><span class="line"> <span class="string">&#x27;OpenAI&#x27;</span>: <span class="string">&#x27;开放人工智能&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;GPT-4&#x27;</span>: <span class="string">&#x27;生成式预训练模型4.0&#x27;</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <p><strong>效果</strong>:强制替换指定词汇,解决机器翻译不准确问题。</p> <h4 id="3私有翻译接口"><a class="anchor" href="#3私有翻译接口">#</a> (3)私有翻译接口</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">translate.<span class="property">service</span>.<span class="title function_">use</span>(<span class="string">&#x27;http://your-api.com/translate&#x27;</span>);</span><br><span class="line"><span class="comment">// 自定义请求头(如API密钥)</span></span><br><span class="line">translate.<span class="property">request</span>.<span class="property">headers</span>.<span class="title function_">set</span>(<span class="string">&#x27;Authorization&#x27;</span>, <span class="string">&#x27;Bearer xxxxxx&#x27;</span>);</span><br></pre></td></tr></table></figure></p> <h4 id="4高级缓存控制"><a class="anchor" href="#4高级缓存控制">#</a> (4)高级缓存控制</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 重写本地缓存策略</span></span><br><span class="line">translate.<span class="property">cache</span>.<span class="title function_">setHandler</span>(&#123;</span><br><span class="line"> <span class="attr">set</span>: <span class="function">(<span class="params">key, value</span>) =&gt;</span> <span class="variable language_">sessionStorage</span>.<span class="title function_">setItem</span>(key, value),</span><br><span class="line"> <span class="attr">get</span>: <span class="function">(<span class="params">key</span>) =&gt;</span> <span class="variable language_">sessionStorage</span>.<span class="title function_">getItem</span>(key)</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <h3 id="33-快速实现自动识别语语言并翻译"><a class="anchor" href="#33-快速实现自动识别语语言并翻译">#</a> 3.3 快速实现 (自动识别语语言并翻译)</h3> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 页面底部语言切换区 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">&quot;DONOTTRANSLATE&quot;</span>&gt;</span></span><br><span class="line"> 语言切换:</span><br><span class="line"> <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:translate.changeLanguage(&#x27;english&#x27;)&quot;</span>&gt;</span>English<span class="tag">&lt;/<span class="name">a</span>&gt;</span> |</span><br><span class="line"> <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:translate.changeLanguage(&#x27;japanese&#x27;)&quot;</span>&gt;</span>日本語<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="variable language_">window</span>.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript"> translate.<span class="property">selectLanguageTag</span>.<span class="property">show</span> = <span class="literal">false</span>; <span class="comment">// 隐藏默认切换器</span></span></span><br><span class="line"><span class="language-javascript"> translate.<span class="property">ignore</span>.<span class="property">id</span>.<span class="title function_">push</span>(<span class="string">&#x27;DONOTTRANSLATE&#x27;</span>); <span class="comment">// 保护切换按钮不被翻译</span></span></span><br><span class="line"><span class="language-javascript"> translate.<span class="title function_">setAutoDiscriminateLocalLanguage</span>(); <span class="comment">// 自动识别用户语种</span></span></span><br><span class="line"><span class="language-javascript"> translate.<span class="property">listener</span>.<span class="title function_">start</span>(); <span class="comment">// 监听动态内容</span></span></span><br><span class="line"><span class="language-javascript">&#125;;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></p> <hr /> <h3 id="34-性能优化与调试技巧"><a class="anchor" href="#34-性能优化与调试技巧">#</a> 3.4 性能优化与调试技巧</h3> <h4 id="1-按需翻译"><a class="anchor" href="#1-按需翻译">#</a> 1. 按需翻译</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 仅翻译特定区块</span></span><br><span class="line">translate.<span class="title function_">execute</span>(&#123;</span><br><span class="line"> <span class="attr">selector</span>: <span class="string">&#x27;#main-content, .article-text&#x27;</span> </span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <h4 id="2-网络优化"><a class="anchor" href="#2-网络优化">#</a> 2. 网络优化</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 启用CDN加速</span></span><br><span class="line">translate.<span class="property">service</span>.<span class="title function_">use</span>(<span class="string">&#x27;client.cdn&#x27;</span>);</span><br></pre></td></tr></table></figure></p> <h4 id="3-错误捕获"><a class="anchor" href="#3-错误捕获">#</a> 3. 错误捕获</h4> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">translate.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;翻译失败:&#x27;</span>, err.<span class="property">message</span>);</span><br><span class="line"> <span class="title function_">fallbackToStaticText</span>(); <span class="comment">// 切换备用方案</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <hr /> <h2 id="五-扩展阅读与参考资料"><a class="anchor" href="#五-扩展阅读与参考资料">#</a> 五、扩展阅读与参考资料</h2> <h3 id="translatejs-补充教程详细"><a class="anchor" href="#translatejs-补充教程详细">#</a> translate.js 补充教程 (详细)</h3> <hr /> <h4 id="第一章基础集成与配置"><a class="anchor" href="#第一章基础集成与配置">#</a> 第一章:基础集成与配置</h4> <h5 id="11-环境搭建与快速启动"><a class="anchor" href="#11-环境搭建与快速启动">#</a> 1.1 环境搭建与快速启动</h5> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 标准集成模式 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.staticfile.net/translate.js/3.12.0/translate.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 设置本地语种为简体中文(影响自动识别逻辑)</span></span></span><br><span class="line"><span class="language-javascript"> translate.<span class="property">language</span>.<span class="title function_">setLocal</span>(<span class="string">&#x27;chinese_simplified&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> </span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 使用边缘计算翻译通道(默认服务节点)</span></span></span><br><span class="line"><span class="language-javascript"> translate.<span class="property">service</span>.<span class="title function_">use</span>(<span class="string">&#x27;client.edge&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> </span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 初始化后立即执行首次翻译</span></span></span><br><span class="line"><span class="language-javascript"> translate.<span class="title function_">execute</span>();</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></p> <p><strong>技术细节</strong>:</p> <ul> <li>使用 <code>setLocal()</code> 方法声明源语言类型,支持 87 种 ISO 标准语言代码</li> <li><code>client.edge</code> 模式采用分布式 CDN 节点,平均响应时间 &lt;200ms</li> <li>自动执行 DOM 扫描,遍历所有文本节点并建立翻译索引</li> </ul> <h5 id="12-服务通道配置"><a class="anchor" href="#12-服务通道配置">#</a> 1.2 服务通道配置</h5> <table> <thead> <tr> <th>通道类型</th> <th>代码示例</th> <th>适用场景</th> <th>并发限制</th> </tr> </thead> <tbody> <tr> <td>公有云基础版</td> <td><code>translate.service.use('client.basic')</code></td> <td>个人博客 / 小型站点</td> <td>100 次 / 分钟</td> </tr> <tr> <td>边缘计算加速版</td> <td><code>translate.service.use('client.edge')</code></td> <td>企业官网 / 中等流量</td> <td>无限制</td> </tr> <tr> <td>私有化部署版</td> <td><code>translate.service.use('http://your-api')</code></td> <td>金融 / 医疗等敏感行业</td> <td>自定义</td> </tr> <tr> <td>企业专线版</td> <td><code>translate.service.use('enterprise.pro')</code></td> <td>跨国业务 / 高 SLA 要求</td> <td>无限制</td> </tr> </tbody> </table> <p><strong>注意事项</strong>:</p> <ul> <li>私有化部署需配置 <code>translate.request.headers.set('X-Auth-Key', 'xxx')</code> 认证</li> <li>企业版需联系官方开通,支持双向 TLS 加密传输</li> </ul> <hr /> <h4 id="第二章核心功能开发"><a class="anchor" href="#第二章核心功能开发">#</a> 第二章:核心功能开发</h4> <h5 id="21-动态内容处理"><a class="anchor" href="#21-动态内容处理">#</a> 2.1 动态内容处理</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 开启实时监控(适用于 Vue/React)</span></span><br><span class="line">translate.<span class="property">listener</span>.<span class="title function_">start</span>(&#123;</span><br><span class="line"> <span class="attr">interval</span>: <span class="number">300</span>, <span class="comment">// DOM 检查间隔(ms)</span></span><br><span class="line"> <span class="attr">depth</span>: <span class="number">5</span> <span class="comment">// 监控嵌套层级</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 自定义忽略规则</span></span><br><span class="line">translate.<span class="property">ignore</span></span><br><span class="line"> .<span class="property">id</span>.<span class="title function_">push</span>(<span class="string">&#x27;ad-container&#x27;</span>) <span class="comment">// 忽略指定 ID</span></span><br><span class="line"> .<span class="property">class</span>.<span class="title function_">push</span>(<span class="string">&#x27;no-translate&#x27;</span>) <span class="comment">// 忽略指定 class</span></span><br><span class="line"> .<span class="property">tag</span>.<span class="title function_">push</span>(<span class="string">&#x27;code&#x27;</span>) <span class="comment">// 忽略代码块</span></span><br><span class="line"> .<span class="property">text</span>.<span class="title function_">push</span>(<span class="string">&#x27;OpenAI&#x27;</span>) <span class="comment">// 保留专有名词</span></span><br><span class="line"> .<span class="property">attr</span>.<span class="title function_">add</span>(<span class="string">&#x27;data-translate&#x27;</span>, <span class="string">&#x27;false&#x27;</span>); <span class="comment">// 自定义属性标记</span></span><br></pre></td></tr></table></figure></p> <p><strong>优化策略</strong>:</p> <ul> <li>使用 MutationObserver 实现增量更新,避免全量扫描</li> <li>通过 <code>translate.refresh(element)</code> 手动刷新指定区域</li> </ul> <h5 id="22-术语库管理"><a class="anchor" href="#22-术语库管理">#</a> 2.2 术语库管理</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 静态术语配置</span></span><br><span class="line">translate.<span class="property">term</span>.<span class="title function_">set</span>(&#123;</span><br><span class="line"> <span class="string">&#x27;GPT-4&#x27;</span>: <span class="string">&#x27;生成式预训练模型4.0&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;CEO&#x27;</span>: <span class="string">&#x27;首席执行官&#x27;</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 动态加载术语库</span></span><br><span class="line"><span class="title function_">fetch</span>(<span class="string">&#x27;/dict/custom.json&#x27;</span>)</span><br><span class="line"> .<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res.<span class="title function_">json</span>())</span><br><span class="line"> .<span class="title function_">then</span>(<span class="function"><span class="params">data</span> =&gt;</span> translate.<span class="property">term</span>.<span class="title function_">merge</span>(data));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 术语优先级配置</span></span><br><span class="line">translate.<span class="property">term</span>.<span class="property">priority</span> = &#123;</span><br><span class="line"> <span class="attr">user</span>: <span class="number">100</span>, <span class="comment">// 用户自定义术语</span></span><br><span class="line"> <span class="attr">system</span>: <span class="number">50</span> <span class="comment">// 系统预设术语</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p> <p><strong>高级特性</strong>:</p> <ul> <li>支持正则表达式匹配: <code>translate.term.set(&#123; '/d&#123;4&#125;-d&#123;2&#125;/': '日期格式' &#125;)</code></li> <li>提供术语版本控制接口 <code>translate.term.version = 'v2.1'</code></li> </ul> <h5 id="23-混合翻译模式"><a class="anchor" href="#23-混合翻译模式">#</a> 2.3 混合翻译模式</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 启用本地缓存翻译</span></span><br><span class="line">translate.<span class="property">cache</span>.<span class="title function_">enable</span>(&#123;</span><br><span class="line"> <span class="attr">ttl</span>: <span class="number">86400</span>, <span class="comment">// 缓存有效期(秒)</span></span><br><span class="line"> <span class="attr">strategy</span>: <span class="string">&#x27;stale&#x27;</span> <span class="comment">// 过期后仍使用旧数据</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 配置离线词库</span></span><br><span class="line">translate.<span class="property">offline</span>.<span class="title function_">load</span>(&#123;</span><br><span class="line"> <span class="string">&#x27;hello&#x27;</span>: &#123;</span><br><span class="line"> <span class="string">&#x27;zh-CN&#x27;</span>: <span class="string">&#x27;你好&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;ja-JP&#x27;</span>: <span class="string">&#x27;こんにちは&#x27;</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 优先级策略设置</span></span><br><span class="line">translate.<span class="property">strategy</span>.<span class="title function_">set</span>(<span class="string">&#x27;hybrid&#x27;</span>, &#123;</span><br><span class="line"> <span class="attr">order</span>: [<span class="string">&#x27;cache&#x27;</span>, <span class="string">&#x27;offline&#x27;</span>, <span class="string">&#x27;api&#x27;</span>]</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <p><strong>性能对比</strong>:</p> <table> <thead> <tr> <th>模式</th> <th>首屏加载</th> <th>二次加载</th> <th>网络依赖</th> </tr> </thead> <tbody> <tr> <td>纯 API</td> <td>1200ms</td> <td>800ms</td> <td>是</td> </tr> <tr> <td>混合模式</td> <td>1500ms</td> <td>200ms</td> <td>部分</td> </tr> <tr> <td>纯离线</td> <td>300ms</td> <td>50ms</td> <td>否</td> </tr> </tbody> </table> <hr /> <h4 id="第三章企业级部署方案"><a class="anchor" href="#第三章企业级部署方案">#</a> 第三章:企业级部署方案</h4> <h5 id="31-私有化架构设计"><a class="anchor" href="#31-私有化架构设计">#</a> 3.1 私有化架构设计</h5> <p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 部署翻译引擎</span></span><br><span class="line">docker run -d \</span><br><span class="line"> -p 8080:80 \</span><br><span class="line"> -v /data/translate:/app/data \</span><br><span class="line"> translate/service:enterprise</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置负载均衡</span></span><br><span class="line">upstream translate_cluster &#123;</span><br><span class="line"> server 10.0.0.1:8080 weight=5;</span><br><span class="line"> server 10.0.0.2:8080 weight=3;</span><br><span class="line"> server 10.0.0.3:8080 weight=2;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p> <p><strong>安全方案</strong>:</p> <ul> <li>传输层:TLS 1.3 + 双向证书认证</li> <li>数据层:AES-256-GCM 端到端加密</li> <li>审计层:全量操作日志记录</li> </ul> <h5 id="32-高可用性配置"><a class="anchor" href="#32-高可用性配置">#</a> 3.2 高可用性配置</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 客户端故障转移策略</span></span><br><span class="line">translate.<span class="property">service</span>.<span class="property">fallback</span> = [</span><br><span class="line"> <span class="string">&#x27;https://node1.your-domain.com&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;https://node2.your-domain.com&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;client.edge&#x27;</span> <span class="comment">// 公有云兜底</span></span><br><span class="line">];</span><br><span class="line"></span><br><span class="line"><span class="comment">// 服务端健康检查</span></span><br><span class="line"><span class="built_in">setInterval</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="title function_">fetch</span>(<span class="string">&#x27;/health&#x27;</span>)</span><br><span class="line"> .<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">if</span> (!res.<span class="property">ok</span>) <span class="title class_">Kubernetes</span>.<span class="title function_">restartPod</span>(<span class="string">&#x27;translate-service&#x27;</span>);</span><br><span class="line"> &#125;);</span><br><span class="line">&#125;, <span class="number">60000</span>);</span><br></pre></td></tr></table></figure></p> <p><strong>SLA 指标</strong>:</p> <table> <thead> <tr> <th>指标</th> <th>目标值</th> <th>监控方式</th> </tr> </thead> <tbody> <tr> <td>可用性</td> <td>99.99%</td> <td>Prometheus</td> </tr> <tr> <td>平均延迟</td> <td>&lt;300ms</td> <td>Elastic APM</td> </tr> <tr> <td>错误率</td> <td>&lt;0.1%</td> <td>Sentry</td> </tr> <tr> <td>并发容量</td> <td>10,000/s</td> <td>LoadRunner</td> </tr> </tbody> </table> <hr /> <h4 id="第四章高级开发技巧"><a class="anchor" href="#第四章高级开发技巧">#</a> 第四章:高级开发技巧</h4> <h5 id="41-自定义渲染引擎"><a class="anchor" href="#41-自定义渲染引擎">#</a> 4.1 自定义渲染引擎</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">CustomRenderer</span> <span class="keyword">extends</span> <span class="title class_ inherited__">translate.Renderer</span> &#123;</span><br><span class="line"> <span class="title function_">onTextNode</span>(<span class="params">node, translation</span>) &#123;</span><br><span class="line"> <span class="keyword">if</span> (node.<span class="property">parentNode</span>.<span class="property">tagName</span> === <span class="string">&#x27;H1&#x27;</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="string">`&lt;span class=&quot;highlight&quot;&gt;<span class="subst">$&#123;translation&#125;</span>&lt;/span&gt;`</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> translation;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line">translate.<span class="property">renderer</span>.<span class="title function_">use</span>(<span class="keyword">new</span> <span class="title class_">CustomRenderer</span>());</span><br></pre></td></tr></table></figure></p> <h5 id="42-翻译流水线扩展"><a class="anchor" href="#42-翻译流水线扩展">#</a> 4.2 翻译流水线扩展</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 添加预处理插件</span></span><br><span class="line">translate.<span class="property">pipeline</span>.<span class="title function_">before</span>(<span class="string">&#x27;translate&#x27;</span>, <span class="function">(<span class="params">text, context</span>) =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> text.<span class="title function_">replace</span>(<span class="regexp">/\b\d&#123;4&#125;\b/g</span>, <span class="string">&#x27;&lt;year&gt;&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 添加后处理插件</span></span><br><span class="line">translate.<span class="property">pipeline</span>.<span class="title function_">after</span>(<span class="string">&#x27;translate&#x27;</span>, <span class="function">(<span class="params">text, context</span>) =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> text.<span class="title function_">replace</span>(<span class="regexp">/&lt;year&gt;/g</span>, <span class="keyword">new</span> <span class="title class_">Date</span>().<span class="title function_">getFullYear</span>());</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <h5 id="43-多模态翻译"><a class="anchor" href="#43-多模态翻译">#</a> 4.3 多模态翻译</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 图片OCR翻译</span></span><br><span class="line">translate.<span class="property">image</span>.<span class="property">translator</span> = <span class="title function_">async</span> (imgElement) =&gt; &#123;</span><br><span class="line"> <span class="keyword">const</span> text = <span class="keyword">await</span> <span class="variable constant_">OCR</span>.<span class="title function_">detect</span>(imgElement.<span class="property">src</span>);</span><br><span class="line"> <span class="keyword">return</span> translate.<span class="title function_">execute</span>(text);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 视频字幕处理</span></span><br><span class="line">translate.<span class="property">video</span>.<span class="property">handle</span> = <span class="function">(<span class="params">videoElement</span>) =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> tracks = videoElement.<span class="property">textTracks</span>;</span><br><span class="line"> tracks.<span class="title function_">forEach</span>(<span class="function"><span class="params">track</span> =&gt;</span> &#123;</span><br><span class="line"> translate.<span class="property">subtitle</span>.<span class="title function_">process</span>(track);</span><br><span class="line"> &#125;);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p> <hr /> <h4 id="第五章调试与优化"><a class="anchor" href="#第五章调试与优化">#</a> 第五章:调试与优化</h4> <h5 id="51-性能分析工具"><a class="anchor" href="#51-性能分析工具">#</a> 5.1 性能分析工具</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 开启性能监控</span></span><br><span class="line">translate.<span class="property">monitor</span>.<span class="title function_">enable</span>(&#123;</span><br><span class="line"> <span class="attr">metrics</span>: [<span class="string">&#x27;dom-parse&#x27;</span>, <span class="string">&#x27;network&#x27;</span>, <span class="string">&#x27;render&#x27;</span>],</span><br><span class="line"> <span class="attr">sampling</span>: <span class="number">0.1</span> <span class="comment">// 10%采样率</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 自定义性能指标</span></span><br><span class="line">translate.<span class="property">monitor</span>.<span class="title function_">define</span>(<span class="string">&#x27;custom-metric&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> performance.<span class="title function_">now</span>() - <span class="variable language_">window</span>.<span class="property">translateStart</span>;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <h5 id="52-内存优化方案"><a class="anchor" href="#52-内存优化方案">#</a> 5.2 内存优化方案</h5> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 分块加载策略</span></span><br><span class="line">translate.<span class="property">chunk</span>.<span class="title function_">set</span>(&#123;</span><br><span class="line"> <span class="attr">size</span>: <span class="number">500</span>, <span class="comment">// 每块500字符</span></span><br><span class="line"> <span class="attr">parallel</span>: <span class="number">3</span> <span class="comment">// 最大并发数</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// DOM 回收机制</span></span><br><span class="line">translate.<span class="property">garbageCollector</span>.<span class="title function_">run</span>(&#123;</span><br><span class="line"> <span class="attr">interval</span>: <span class="number">30000</span>,</span><br><span class="line"> <span class="attr">policy</span>: <span class="string">&#x27;aggressive&#x27;</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <hr /> <h4 id="结语"><a class="anchor" href="#结语">#</a> 结语</h4> <p>您还可以可通过 <span class="exturl" data-url="aHR0cHM6Ly9yZXMuenZvLmNuL3RyYW5zbGF0ZS9kZW1vLmh0bWw=">官方演示站点</span> 体验完整功能,更多企业级方案请参考 <span class="exturl" data-url="aHR0cHM6Ly9naXRlZS5jb20vbWFpbF9vc2MvdHJhbnNsYXRl">Gitee 仓库</span>。</p> <h3 id="参考资料"><a class="anchor" href="#参考资料">#</a> 参考资料</h3> <ul> <li><span class="exturl" data-url="aHR0cDovL3RyYW5zbGF0ZS56dm8uY24vNDMwODYuaHRtbA==">translate.js 官方文档: http://translate.zvo.cn/43086.html</span></li> <li><span class="exturl" data-url="aHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL3RyYW5zbGF0ZQ==">谷歌翻译私有化部署指南: https://cloud.google.com/translate</span></li> <li><span class="exturl" data-url="aHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vc2VhcmNoL2RvY3MvYWR2YW5jZWQvY3Jhd2xpbmcvbWFuYWdpbmctbXVsdGktcmVnaW9uYWwtc2l0ZXM=">多语言 SEO 优化策略: https://developers.google.com/search/docs/advanced/crawling/managing-multi-regional-sites</span></li> </ul> <hr /> <p><strong>提示</strong>:访问 <a href="https://jdjwzx233.cn">本站: jdjwzx233.cn</a> 点击页面底部语言切换按钮,可实时体验 translate.js 的实际效果。</p> <h2 id="结尾"><a class="anchor" href="#结尾">#</a> 结尾</h2> <p>非常感谢你能看到这里,如有什么问题欢迎在评论区中提出!如果可以的话,请订阅我的网站:<a href="https://jdjwzx233.cn/Subscribe">https://jdjwzx233.cn/Subscribe</a><br /> 如果你觉得我的博客不错的话,可以赞助我 (・̀ ω・́)✧:<a href="https://jdjwzx233.cn/support">https://jdjwzx233.cn/support</a>。</p>

2025/5/1
阅读更多

使用Netlify搭建反向代理

<div class="note warning"> <p><strong>1. 免责声明</strong></p> <p>在撰写本文时,我旨在为技术爱好者提供有关如何使用 Netlify 搭建反向代理的技术指导和示例。请注意,本文中的信息和建议仅供参考,具体实施可能会因实际情况而有所不同。使用本文提供的方法和步骤时,请确保遵循当地法律法规,并充分考虑网络安全和数据保护的要求。</p> <p>本文作者和发布平台对因使用本文内容而导致的任何直接或间接损失、损害或法律责任不承担任何责任。建议在实施任何技术方案之前,进行充分的测试和风险评估,并寻求专业意见,以确保符合适用的法律和行业标准。</p> <p><strong>2. 合法用途声明</strong></p> <p>请遵守相关法律法规,包括但不限于《中华人民共和国网络安全法》和《互联网信息服务管理办法》。请确保在使用 Netlify 或其他服务时:</p> <ol> <li><strong>合法合规</strong>:确保所搭建的反向代理不用于违反法律法规的活动,包括但不限于绕过审查、非法数据传输、或其他违法用途。</li> <li><strong>尊重版权和隐私</strong>:遵守版权法律,确保所代理的内容不侵犯第三方的知识产权。同时,保障用户隐私,遵循数据保护的相关要求。</li> <li><strong>网络安全</strong>:采取必要的安全措施,防止反向代理服务被用于恶意目的,保障系统和用户数据的安全。</li> <li><strong>信息透明</strong>:确保提供的服务信息清晰透明,用户可以明确知晓反向代理的用途和可能的风险。</li> </ol> </div> <h2 id="前言摘要"><a class="anchor" href="#前言摘要">#</a> 前言 / 摘要</h2> <p>在当今互联网环境下,尤其是部分国外和国内网站常常由于 DNS 污染和其他原因而无法正常访问,这成为了许多用户的一大困扰。此外,有些网站虽然仅能通过 IP 地址进行访问,却无法绑定自定义域名,这同样限制了其灵活性和可用性。为了解决这些问题,搭建一个反向代理服务器成为了一个有效的解决方案。反向代理不仅可以帮助用户绕过 DNS 污染的问题,还能让我们以自定义的域名来访问那些仅能通过 IP 地址访问的网站。</p> <p>在本篇文章中,我们将利用 Netlify 这一强大而易于使用的工具来搭建反向代理。Netlify 的强大之处在于其简洁的配置过程和强大的功能,使得即使是对技术不太熟悉的用户也能轻松上手。要完成这项任务,你只需具备两个基本条件:一个 Netlify 账号和一个 GitHub 账号。接下来,我们将详细介绍如何通过这两个账户配置反向代理。</p> <h2 id="正文"><a class="anchor" href="#正文">#</a> 正文</h2> <div class="note info"> <p><strong>温馨提示</strong><br /> 标题后面有 (选) 的为后台相关内容,如不需要可以跳过</p> </div> <h3 id="第一步-准备用于搭建反代的环境"><a class="anchor" href="#第一步-准备用于搭建反代的环境">#</a> 第一步 准备用于搭建反代的环境</h3> <h4 id="1-创建储存库"><a class="anchor" href="#1-创建储存库">#</a> 1. 创建储存库</h4> <p>创建一个用于存放 Netlify 配置文件的 GitHub 储存库</p> <p>如图:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/1726582387299_23298110f4e294999cce8e5ddb9919ed.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/1726582387299_23298110f4e294999cce8e5ddb9919ed.png" /></p> <h4 id="2-创建配置文件"><a class="anchor" href="#2-创建配置文件">#</a> 2. 创建配置文件</h4> <p>新建名为 <code>netlify.toml</code> 的配置文件</p> <p>如图:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_b32990708afc79c8ac57533641e18942.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_b32990708afc79c8ac57533641e18942.png" /></p> <p>文件内容为:</p> <p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[[redirects]]</span></span><br><span class="line"> <span class="attr">from</span> = <span class="string">&quot;/*&quot;</span></span><br><span class="line"> <span class="attr">to</span> = <span class="string">&quot;https://github.com/:splat&quot;</span></span><br><span class="line"> <span class="attr">status</span> = <span class="number">200</span></span><br></pre></td></tr></table></figure></p> <h4 id="选择性内容"><a class="anchor" href="#选择性内容">#</a> 选择性内容</h4> <p>再新建一个储存库,用于搭建管理后台 (选)</p> <p>如图:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/1726582387299_23298110f4e294999cce8e5ddb9919ed.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/1726582387299_23298110f4e294999cce8e5ddb9919ed.png" /></p> <h5 id="储存库中包含的文件选"><a class="anchor" href="#储存库中包含的文件选">#</a> 储存库中包含的文件 (选):</h5> <p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">│ index.html</span><br><span class="line">│ package.json</span><br><span class="line">│ README.md</span><br><span class="line">│</span><br><span class="line">└─netlify</span><br><span class="line">  └─functions</span><br><span class="line">    auth-callback.js</span><br><span class="line">    check-auth.js</span><br><span class="line">    update-redirect.js</span><br></pre></td></tr></table></figure></p> <ol> <li><strong>index.html</strong>:应用的主要前端页面,包含用户登录和配置反向代理的表单。(选)</li> </ol> <div class="note info"> <p><strong>温馨提示</strong><br /> 请在代码中的【这里填你的反代网站,不是后台】中填入你的反代网址 (就是用存放 Netlify 配置文件的 GitHub 储存库搭建的那个)【这里填你的 GitHub clientid】中填入你的 GitHub clientid,获取方法见下文</p> </div> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;zh&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">title</span>&gt;</span>反代配置<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">body</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">font-family</span>: Arial, sans-serif;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(to bottom, <span class="number">#87CEFA</span>, <span class="number">#FFFFFF</span>);</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">display</span>: flex;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">justify-content</span>: center;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">align-items</span>: center;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">height</span>: <span class="number">100vh</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">overflow-x</span>: hidden;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.container</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">width</span>: <span class="number">90%</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">max-width</span>: <span class="number">500px</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">h1</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: <span class="number">#333</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-bottom</span>: <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">font-size</span>: <span class="number">1.8em</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">form</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background</span>: <span class="number">#f9f9f9</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-radius</span>: <span class="number">15px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">padding</span>: <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">4px</span> <span class="number">8px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>);</span></span><br><span class="line"><span class="language-css"> <span class="attribute">transition</span>: transform <span class="number">0.3s</span> ease-in-out;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">form</span><span class="selector-pseudo">:hover</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">1.02</span>);</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">label</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">font-size</span>: <span class="number">1.2em</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">display</span>: block;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-bottom</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: <span class="number">#555</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">input</span><span class="selector-attr">[type=<span class="string">&quot;url&quot;</span>]</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">22px</span>);</span></span><br><span class="line"><span class="language-css"> <span class="attribute">padding</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#ddd</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-bottom</span>: <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">font-size</span>: <span class="number">1em</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">box-sizing</span>: border-box;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">button</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background-color</span>: <span class="number">#87CEFA</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: white;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border</span>: none;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">cursor</span>: pointer;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">font-size</span>: <span class="number">1.1em</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">transition</span>: background-color <span class="number">0.3s</span> ease-in-out;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-tag">button</span><span class="selector-pseudo">:hover</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background-color</span>: <span class="number">#00BFFF</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-id">#message</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">font-size</span>: <span class="number">1.2em</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: <span class="number">#333</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-top</span>: <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.error-container</span>,</span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.success-container</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">display</span>: none;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background</span>: <span class="number">#f0f8ff</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#d4edda</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">padding</span>: <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-top</span>: <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">4px</span> <span class="number">8px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>);</span></span><br><span class="line"><span class="language-css"> <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.error-container</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-color</span>: <span class="number">#f5c6cb</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background</span>: <span class="number">#f8d7da</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: <span class="number">#721c24</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.success-container</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-color</span>: <span class="number">#c3e6cb</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background</span>: <span class="number">#d4edda</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: <span class="number">#155724</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.error-container</span> <span class="selector-tag">p</span>,</span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.success-container</span> <span class="selector-tag">p</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.success-container</span> <span class="selector-tag">button</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-top</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background-color</span>: <span class="number">#4CAF50</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border</span>: none;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.success-container</span> <span class="selector-tag">button</span><span class="selector-pseudo">:hover</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background-color</span>: <span class="number">#45a049</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.tooltip</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">position</span>: relative;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">display</span>: inline-block;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">cursor</span>: pointer;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.tooltip</span> <span class="selector-class">.tooltiptext</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">visibility</span>: hidden;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">width</span>: <span class="number">200px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">background-color</span>: <span class="number">#333</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">border-radius</span>: <span class="number">6px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">padding</span>: <span class="number">5px</span> <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">z-index</span>: <span class="number">1</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">bottom</span>: <span class="number">125%</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">left</span>: <span class="number">50%</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">margin-left</span>: -<span class="number">100px</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">opacity</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">transition</span>: opacity <span class="number">0.3s</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-class">.tooltip</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.tooltiptext</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">visibility</span>: visible;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">opacity</span>: <span class="number">1</span>;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css"> <span class="selector-id">#loginContainer</span> &#123;</span></span><br><span class="line"><span class="language-css"> <span class="attribute">display</span>: none;</span></span><br><span class="line"><span class="language-css"> &#125;</span></span><br><span class="line"><span class="language-css"> </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;container&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">h1</span>&gt;</span>反代配置器<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;loginContainer&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">p</span>&gt;</span>请登录以访问此页面。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&quot;loginButton&quot;</span>&gt;</span>使用 GitHub 登录<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">form</span> <span class="attr">id</span>=<span class="string">&quot;redirectForm&quot;</span> <span class="attr">style</span>=<span class="string">&quot;display: none;&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tooltip&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">label</span> <span class="attr">for</span>=<span class="string">&quot;website&quot;</span>&gt;</span>请输入要反代到的网址:<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;tooltiptext&quot;</span>&gt;</span>请输入完整的 URL 地址,例如 https://example.com<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;url&quot;</span> <span class="attr">id</span>=<span class="string">&quot;website&quot;</span> <span class="attr">name</span>=<span class="string">&quot;website&quot;</span> <span class="attr">required</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;errorMessage&quot;</span> <span class="attr">class</span>=<span class="string">&quot;error-container&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">p</span> <span class="attr">id</span>=<span class="string">&quot;errorStatusMessage&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;successMessage&quot;</span> <span class="attr">class</span>=<span class="string">&quot;success-container&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">p</span> <span class="attr">id</span>=<span class="string">&quot;successStatusMessage&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&quot;redirectButton&quot;</span> <span class="attr">style</span>=<span class="string">&quot;display: none;&quot;</span>&gt;</span>前往反代网站<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">checkAuthentication</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&#x27;/.netlify/functions/check-auth&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> result = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">if</span> (result.<span class="property">authenticated</span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;loginContainer&#x27;</span>).<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;redirectForm&#x27;</span>).<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;loginContainer&#x27;</span>).<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;redirectForm&#x27;</span>).<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> &#125;</span></span><br><span class="line"><span class="language-javascript"> &#125;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;loginButton&#x27;</span>).<span class="title function_">addEventListener</span>(<span class="string">&#x27;click&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">href</span> = <span class="string">`https://github.com/login/oauth/authorize?client_id=【这里填你的GitHub clientid】&amp;redirect_uri=<span class="subst">$&#123;<span class="built_in">encodeURIComponent</span>(<span class="variable language_">window</span>.location.origin + <span class="string">&#x27;/.netlify/functions/auth-callback&#x27;</span>)&#125;</span>`</span>;</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;redirectForm&#x27;</span>).<span class="title function_">addEventListener</span>(<span class="string">&#x27;submit&#x27;</span>, <span class="title function_">async</span> (event) =&gt; &#123;</span></span><br><span class="line"><span class="language-javascript"> event.<span class="title function_">preventDefault</span>();</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> website = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;website&#x27;</span>).<span class="property">value</span>;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> urlPattern = <span class="regexp">/^https?:\/\/[^\/]+$/</span>;</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> errorMessageElement = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;errorStatusMessage&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> successMessageElement = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;successStatusMessage&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> errorContainer = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;errorMessage&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> successContainer = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;successMessage&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> redirectButton = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;redirectButton&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">if</span> (!urlPattern.<span class="title function_">test</span>(website)) &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> suggestion = website.<span class="title function_">replace</span>(<span class="regexp">/\/+$/</span>, <span class="string">&#x27;&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"> errorMessageElement.<span class="property">innerText</span> = <span class="string">`输入的 URL 格式不正确。请确保网址以 &#x27;https://example.com&#x27; 形式输入。你可能的正确输入是:<span class="subst">$&#123;suggestion&#125;</span>`</span>;</span></span><br><span class="line"><span class="language-javascript"> errorContainer.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> successContainer.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">return</span>;</span></span><br><span class="line"><span class="language-javascript"> &#125;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&#x27;/.netlify/functions/update-redirect&#x27;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">method</span>: <span class="string">&#x27;POST&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">headers</span>: &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span></span></span><br><span class="line"><span class="language-javascript"> &#125;,</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; website &#125;)</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">const</span> result = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">if</span> (result.<span class="property">message</span> === <span class="string">&#x27;Redirect updated successfully!&#x27;</span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> successMessageElement.<span class="property">innerText</span> = <span class="string">&#x27;反代配置成功!请等待服务器更新,预计1分钟。&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> successContainer.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> errorContainer.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> redirectButton.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;inline-block&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> redirectButton.<span class="title function_">addEventListener</span>(<span class="string">&#x27;click&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">href</span> = <span class="string">&#x27;【这里填你的反代网站,不是后台】&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"> &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript"> errorMessageElement.<span class="property">innerText</span> = <span class="string">`配置失败:<span class="subst">$&#123;result.message&#125;</span>`</span>;</span></span><br><span class="line"><span class="language-javascript"> errorContainer.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> successContainer.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript"> &#125;</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// Initialize the authentication check</span></span></span><br><span class="line"><span class="language-javascript"> <span class="title function_">checkAuthentication</span>();</span></span><br><span class="line"><span class="language-javascript"> </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure></p> <ol start="2"> <li><strong>/netlify/functions/auth-callback.js</strong>:处理 GitHub OAuth 回调的函数,设置用户的登录状态。(选)</li> </ol> <p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">exports</span>.<span class="property">handler</span> = <span class="keyword">async</span> <span class="keyword">function</span>(<span class="params">event, context</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> clientId = process.<span class="property">env</span>.<span class="property">GITHUB_CLIENT_ID</span>;</span><br><span class="line"> <span class="keyword">const</span> clientSecret = process.<span class="property">env</span>.<span class="property">GITHUB_CLIENT_SECRET</span>;</span><br><span class="line"> <span class="keyword">const</span> allowedUsers = process.<span class="property">env</span>.<span class="property">ALLOWED_USERS</span>.<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>);</span><br><span class="line"> <span class="keyword">const</span> jwtSecret = process.<span class="property">env</span>.<span class="property">JWT_SECRET</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> code = event.<span class="property">queryStringParameters</span>.<span class="property">code</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!code) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">400</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;Missing code parameter&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> fetch = (<span class="keyword">await</span> <span class="keyword">import</span>(<span class="string">&#x27;node-fetch&#x27;</span>)).<span class="property">default</span>;</span><br><span class="line"> <span class="keyword">const</span> jwt = (<span class="keyword">await</span> <span class="keyword">import</span>(<span class="string">&#x27;jsonwebtoken&#x27;</span>)).<span class="property">default</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">`https://github.com/login/oauth/access_token`</span>, &#123;</span><br><span class="line"> <span class="attr">method</span>: <span class="string">&#x27;POST&#x27;</span>,</span><br><span class="line"> <span class="attr">headers</span>: &#123;</span><br><span class="line"> <span class="string">&#x27;Accept&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123;</span><br><span class="line"> <span class="attr">client_id</span>: clientId,</span><br><span class="line"> <span class="attr">client_secret</span>: clientSecret,</span><br><span class="line"> <span class="attr">code</span>: code</span><br><span class="line"> &#125;)</span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> data = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (data.<span class="property">error</span>) &#123;</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(data.<span class="property">error_description</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> userResponse = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&#x27;https://api.github.com/user&#x27;</span>, &#123;</span><br><span class="line"> <span class="attr">headers</span>: &#123;</span><br><span class="line"> <span class="title class_">Authorization</span>: <span class="string">`token <span class="subst">$&#123;data.access_token&#125;</span>`</span></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> userInfo = <span class="keyword">await</span> userResponse.<span class="title function_">json</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (allowedUsers.<span class="title function_">includes</span>(userInfo.<span class="property">login</span>)) &#123;</span><br><span class="line"> <span class="keyword">const</span> token = jwt.<span class="title function_">sign</span>(&#123; <span class="attr">username</span>: userInfo.<span class="property">login</span> &#125;, jwtSecret, &#123; <span class="attr">expiresIn</span>: <span class="string">&#x27;1h&#x27;</span> &#125;);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">302</span>,</span><br><span class="line"> <span class="attr">headers</span>: &#123;</span><br><span class="line"> <span class="string">&#x27;Set-Cookie&#x27;</span>: <span class="string">`token=<span class="subst">$&#123;token&#125;</span>; Path=/; HttpOnly`</span>,</span><br><span class="line"> <span class="string">&#x27;Location&#x27;</span>: <span class="string">&#x27;/&#x27;</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="attr">body</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line"> &#125;;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">403</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;Unauthorized&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">500</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="string">`Error: <span class="subst">$&#123;error.message&#125;</span>`</span></span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p> <ol start="3"> <li><strong>/netlify/functions/check-auth.js</strong>:检查用户是否已登录的函数。(选)</li> </ol> <p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">exports</span>.<span class="property">handler</span> = <span class="keyword">async</span> <span class="keyword">function</span>(<span class="params">event, context</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> jwtSecret = process.<span class="property">env</span>.<span class="property">JWT_SECRET</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> cookieHeader = event.<span class="property">headers</span>.<span class="property">cookie</span> || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line"> <span class="keyword">const</span> cookies = <span class="title class_">Object</span>.<span class="title function_">fromEntries</span>(cookieHeader.<span class="title function_">split</span>(<span class="string">&#x27;; &#x27;</span>).<span class="title function_">map</span>(<span class="function"><span class="params">cookie</span> =&gt;</span> cookie.<span class="title function_">split</span>(<span class="string">&#x27;=&#x27;</span>)));</span><br><span class="line"> <span class="keyword">const</span> token = cookies.<span class="property">token</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> jwt = (<span class="keyword">await</span> <span class="keyword">import</span>(<span class="string">&#x27;jsonwebtoken&#x27;</span>)).<span class="property">default</span>;</span><br><span class="line"> jwt.<span class="title function_">verify</span>(token, jwtSecret);</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">200</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">authenticated</span>: <span class="literal">true</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">403</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">authenticated</span>: <span class="literal">false</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p> <ol start="4"> <li><strong>/netlify/functions/update-redirect.js</strong>:处理反向代理配置的函数。(选)</li> </ol> <div class="note info"> <p><strong>温馨提示</strong><br /> 请在代码中的【这里填入你的 GitHub 用户名】【用于存放 Netlify 配置文件的 GitHub 储存库名称】中分别填入你的 GitHub 用户名和用于存放 Netlify 配置文件的 GitHub 储存库名称,获取方法见下文</p> </div> <p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">exports</span>.<span class="property">handler</span></span><br><span class="line"><span class="keyword">const</span> jwtSecret = process.<span class="property">env</span>.<span class="property">JWT_SECRET</span>;</span><br><span class="line"> <span class="keyword">const</span> allowedUsers = process.<span class="property">env</span>.<span class="property">ALLOWED_USERS</span>.<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> cookieHeader = event.<span class="property">headers</span>.<span class="property">cookie</span> || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line"> <span class="keyword">const</span> cookies = <span class="title class_">Object</span>.<span class="title function_">fromEntries</span>(cookieHeader.<span class="title function_">split</span>(<span class="string">&#x27;; &#x27;</span>).<span class="title function_">map</span>(<span class="function"><span class="params">cookie</span> =&gt;</span> cookie.<span class="title function_">split</span>(<span class="string">&#x27;=&#x27;</span>)));</span><br><span class="line"> <span class="keyword">const</span> token = cookies.<span class="property">token</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> decodedToken;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> jwt = (<span class="keyword">await</span> <span class="keyword">import</span>(<span class="string">&#x27;jsonwebtoken&#x27;</span>)).<span class="property">default</span>;</span><br><span class="line"> decodedToken = jwt.<span class="title function_">verify</span>(token, jwtSecret);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">403</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;Unauthorized&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!allowedUsers.<span class="title function_">includes</span>(decodedToken.<span class="property">username</span>)) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">403</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;Unauthorized&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> &#123; <span class="title class_">Octokit</span> &#125; = <span class="keyword">await</span> <span class="keyword">import</span>(<span class="string">&#x27;@octokit/rest&#x27;</span>);</span><br><span class="line"> <span class="keyword">const</span> octokit = <span class="keyword">new</span> <span class="title class_">Octokit</span>(&#123;</span><br><span class="line"> <span class="attr">auth</span>: process.<span class="property">env</span>.<span class="property">GITHUB_TOKEN</span></span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> &#123; website &#125; = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(event.<span class="property">body</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!website) &#123;</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">400</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;No website provided&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> fetch = (<span class="keyword">await</span> <span class="keyword">import</span>(<span class="string">&#x27;node-fetch&#x27;</span>)).<span class="property">default</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> &#123; <span class="attr">data</span>: fileData &#125; = <span class="keyword">await</span> octokit.<span class="property">repos</span>.<span class="title function_">getContent</span>(&#123;</span><br><span class="line"> <span class="attr">owner</span>: <span class="string">&#x27;【这里填入你的GitHub用户名】&#x27;</span>,</span><br><span class="line"> <span class="attr">repo</span>: <span class="string">&#x27;【用于存放Netlify配置文件的GitHub储存库名称】&#x27;</span>,</span><br><span class="line"> <span class="attr">path</span>: <span class="string">&#x27;netlify.toml&#x27;</span></span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> content = <span class="title class_">Buffer</span>.<span class="title function_">from</span>(fileData.<span class="property">content</span>, <span class="string">&#x27;base64&#x27;</span>).<span class="title function_">toString</span>();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">const</span> newContent = content.<span class="title function_">replace</span>(<span class="regexp">/to\s*=\s*&quot;[^&quot;]+&quot;/</span>, <span class="string">`to = &quot;<span class="subst">$&#123;website&#125;</span>/:splat&quot;`</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">await</span> octokit.<span class="property">repos</span>.<span class="title function_">createOrUpdateFileContents</span>(&#123;</span><br><span class="line"> <span class="attr">owner</span>: <span class="string">&#x27;【这里填入你的GitHub用户名】&#x27;</span>,</span><br><span class="line"> <span class="attr">repo</span>: <span class="string">&#x27;【用于存放Netlify配置文件的GitHub储存库名称】&#x27;</span>,</span><br><span class="line"> <span class="attr">path</span>: <span class="string">&#x27;netlify.toml&#x27;</span>,</span><br><span class="line"> <span class="attr">message</span>: <span class="string">&#x27;Update redirect URL&#x27;</span>,</span><br><span class="line"> <span class="attr">content</span>: <span class="title class_">Buffer</span>.<span class="title function_">from</span>(newContent).<span class="title function_">toString</span>(<span class="string">&#x27;base64&#x27;</span>),</span><br><span class="line"> <span class="attr">sha</span>: fileData.<span class="property">sha</span></span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">200</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;Redirect updated successfully!&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(error);</span><br><span class="line"> <span class="keyword">return</span> &#123;</span><br><span class="line"> <span class="attr">statusCode</span>: <span class="number">500</span>,</span><br><span class="line"> <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="attr">message</span>: <span class="string">&#x27;Failed to update redirect&#x27;</span> &#125;)</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p> <ol start="5"> <li><strong>package.json</strong>:存放依赖的文件。(选)<br /> <figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Rcs,</span></span><br><span class="line"><span class="string"> &quot;</span>version<span class="string">&quot;: &quot;</span><span class="number">1.0</span><span class="number">.0</span><span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>description<span class="string">&quot;: &quot;</span>A reverse proxy configurator with GitHub authentication deployed on Netlify.<span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>main<span class="string">&quot;: &quot;</span>index.js<span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>scripts<span class="string">&quot;: &#123;</span></span><br><span class="line"><span class="string"> &quot;</span>start<span class="string">&quot;: &quot;</span>netlify dev<span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>build<span class="string">&quot;: &quot;</span>netlify build<span class="string">&quot;</span></span><br><span class="line"><span class="string"> &#125;,</span></span><br><span class="line"><span class="string"> &quot;</span>dependencies<span class="string">&quot;: &#123;</span></span><br><span class="line"><span class="string"> &quot;</span>@octokit/rest<span class="string">&quot;: &quot;</span>^<span class="number">19.0</span><span class="number">.7</span><span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>jsonwebtoken<span class="string">&quot;: &quot;</span>^<span class="number">9.0</span><span class="number">.2</span><span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>node-fetch<span class="string">&quot;: &quot;</span>^<span class="number">3.3</span><span class="number">.2</span><span class="string">&quot;</span></span><br><span class="line"><span class="string"> &#125;,</span></span><br><span class="line"><span class="string"> &quot;</span>devDependencies<span class="string">&quot;: &#123;</span></span><br><span class="line"><span class="string"> &quot;</span>netlify-cli<span class="string">&quot;: &quot;</span>^<span class="number">15.0</span><span class="number">.0</span><span class="string">&quot;</span></span><br><span class="line"><span class="string"> &#125;,</span></span><br><span class="line"><span class="string"> &quot;</span>engines<span class="string">&quot;: &#123;</span></span><br><span class="line"><span class="string"> &quot;</span>node<span class="string">&quot;: &quot;</span>&gt;=<span class="number">16.</span>x<span class="string">&quot;</span></span><br><span class="line"><span class="string"> &#125;,</span></span><br><span class="line"><span class="string"> &quot;</span>author<span class="string">&quot;: &quot;</span>j23<span class="string">&quot;,</span></span><br><span class="line"><span class="string"> &quot;</span>license<span class="string">&quot;: &quot;</span>MIT<span class="string">&quot;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure></li> </ol> <h3 id="第二步-配置netlify"><a class="anchor" href="#第二步-配置netlify">#</a> 第二步 配置 Netlify</h3> <h4 id="1-创建一个站点"><a class="anchor" href="#1-创建一个站点">#</a> 1. 创建一个站点</h4> <p>如图:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_24ce560b9f2dc57d0d6f51bfebae6b71.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_24ce560b9f2dc57d0d6f51bfebae6b71.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_d0c9459ade47c217db7d74d4c0dc815f.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_d0c9459ade47c217db7d74d4c0dc815f.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_ee9fc4b5245b51661e8a91a2c509c959.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_ee9fc4b5245b51661e8a91a2c509c959.png" /></p> <ol start="4"> <li>选择你的用于存放 Netlify 配置文件的 GitHub 储存库</li> </ol> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_1f40a4eb848a567c69eee524172ba04a.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_1f40a4eb848a567c69eee524172ba04a.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE_17-9-2024_23297_app.netlify.com_9d63c0ed9504f5a945c156f026d8fc1f.jpeg" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/屏幕截图_17-9-2024_23297_app.netlify.com_9d63c0ed9504f5a945c156f026d8fc1f.jpeg" /></p> <h4 id="2配置自定义域名"><a class="anchor" href="#2配置自定义域名">#</a> 2. 配置自定义域名</h4> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_03b28a83de8ee0c91accd703fdca989d.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_03b28a83de8ee0c91accd703fdca989d.png" /></p> <div class="note info"> <p>自此所有基本操作已经完成,如果不需要配置后台,你只需要修改 Netlify 配置文件中的链接,就可以实现更换需要代理的网站。</p> </div> <p>修改内容如下 (注意!,网址格式必须为 https://example.com/,不能删去 https:// 也不能删去最后的 /):</p> <p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[[redirects]]</span></span><br><span class="line"> <span class="attr">from</span> = <span class="string">&quot;/*&quot;</span></span><br><span class="line"> <span class="attr">to</span> = <span class="string">&quot;【修改这里】:splat&quot;</span></span><br><span class="line"> <span class="attr">status</span> = <span class="number">200</span></span><br></pre></td></tr></table></figure></p> <h3 id="选择性内容-2"><a class="anchor" href="#选择性内容-2">#</a> 选择性内容</h3> <h4 id="一github-登录"><a class="anchor" href="#一github-登录">#</a> 一.GitHub 登录</h4> <p>使用 GitHub 进行 OAuth 登录,确保只有授权用户可以访问配置功能。</p> <h5 id="第一步"><a class="anchor" href="#第一步">#</a> 第一步:</h5> <p>打开下面网址,并填好配置<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL3NldHRpbmdzL2FwcGxpY2F0aW9ucy9uZXc="> https://github.com/settings/applications/new</span></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_08ba52609ba4bfe62f2563933cbba566.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_08ba52609ba4bfe62f2563933cbba566.png" /></p> <h5 id="第二步"><a class="anchor" href="#第二步">#</a> 第二步:</h5> <p>获取 Client ID,并生成 Client secrets,后面要用</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_038e6d1208bd8e0990b3b595a40f256e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_038e6d1208bd8e0990b3b595a40f256e.png" /><br /> 2.<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_0572103207489f7a3ae48fd3a3e2a2b6.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_0572103207489f7a3ae48fd3a3e2a2b6.png" /></p> <div class="note warning"> <p><strong>警告!</strong><br /> 请妥善保管好你的 Client secrets!</p> </div> <h4 id="二配置用于修改储存库的密钥"><a class="anchor" href="#二配置用于修改储存库的密钥">#</a> 二。配置用于修改储存库的密钥</h4> <ol> <li> <p>打开下面的网址<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL3NldHRpbmdzL3Rva2Vucw=="> https://github.com/settings/tokens</span></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_29ac6da4b073ffc18764a3748bcc885a.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_29ac6da4b073ffc18764a3748bcc885a.png" /></p> </li> <li> <p>填入相关内容,选择不过期,勾选储存库</p> </li> </ol> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_bdfead6a17b8cdf05219e9ae7e9bd799.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_bdfead6a17b8cdf05219e9ae7e9bd799.png" /></p> <ol start="3"> <li>获取到密钥</li> </ol> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_56563b4d40ebd00c25c2ddbc0aea9565.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_56563b4d40ebd00c25c2ddbc0aea9565.png" /></p> <div class="note warning"> <p><strong>警告!</strong><br /> 请妥善保管好你的密钥</p> </div> <h4 id="三配置netlify"><a class="anchor" href="#三配置netlify">#</a> 三。配置 Netlify</h4> <h5 id="第一步创建站点"><a class="anchor" href="#第一步创建站点">#</a> 第一步:创建站点</h5> <p>如图:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_24ce560b9f2dc57d0d6f51bfebae6b71.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_24ce560b9f2dc57d0d6f51bfebae6b71.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_d0c9459ade47c217db7d74d4c0dc815f.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_d0c9459ade47c217db7d74d4c0dc815f.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_ee9fc4b5245b51661e8a91a2c509c959.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_ee9fc4b5245b51661e8a91a2c509c959.png" /></p> <ol start="4"> <li>选择你的后台储存库</li> </ol> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_1f40a4eb848a567c69eee524172ba04a.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_1f40a4eb848a567c69eee524172ba04a.png" /></p> <ol start="5"> <li>填入环境变量<br /> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ALLOWED_USERS:你授权使用后台的GitHub用户名,用半角逗号隔开,如果只有一个用户,则无需逗号。如:用户名1,用户名2</span><br><span class="line">GITHUB_CLIENT_ID:你的CLIENT_ID</span><br><span class="line">GITHUB_CLIENT_SECRET:你的CLIENT_SECRET</span><br><span class="line">GITHUB_TOKEN:你的GitHub账号密钥</span><br><span class="line">JWT_SECRET:一个随机的不限位数的字符串,如wfhehfihwjdwefnabwaieu72dub3uigfvqty2UGQWADIWGADIY3UGF378</span><br></pre></td></tr></table></figure></li> </ol> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_5bb90ceb6dd257c5c3e51cd20423f929.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_5bb90ceb6dd257c5c3e51cd20423f929.png" /><br /> 如果这一步漏掉了,可以在下面页面找到并补充</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_1184a04b95f68e809a5360a9e5925ecc.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/18/image_1184a04b95f68e809a5360a9e5925ecc.png" /></p> <h5 id="第二步配置自定义域名"><a class="anchor" href="#第二步配置自定义域名">#</a> 第二步。配置自定义域名</h5> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_03b28a83de8ee0c91accd703fdca989d.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/24/9/17/image_03b28a83de8ee0c91accd703fdca989d.png" /></p> <h2 id="结尾"><a class="anchor" href="#结尾">#</a> 结尾</h2> <p>非常感谢你能看到这里,如有什么问题欢迎在评论区中提出!如果可以的话,请订阅我的网站:<a href="https://jdjwzx233.cn/Subscribe">https://jdjwzx233.cn/Subscribe</a><br /> 如果你觉得我的博客不错的话,可以赞助我 (・̀ ω・́)✧:<a href="https://jdjwzx233.cn/support">https://jdjwzx233.cn/support</a>。</p>

2024/9/17
阅读更多

搭建jsdelivr镜像(又拍云/nginx/cfwokers/Deno)

<h2 id="前言"><a class="anchor" href="#前言">#</a> 前言</h2> <p>jsDelivr —— 一个免费、快速、可靠的为 JS 和开源项目服务的 CDN。但是由于国内访问速度慢,加之 jsDelivr 备案被吊销和 DNS 污染常出现,国内使用了 jsDelivr 的站点常常出现访问速度慢的问题。<br /> 你可能会问,为什么不去使用别人的镜像站呢?俗话说 &quot;自己动手,丰衣足食&quot;,自建镜像站可以让你更好地掌握自己的数据和服务。使用第三方镜像站存在一些潜在的风险和不确定性。首先,你无法确定第三方镜像站的可靠性和稳定性,它们可能在任何时候关闭或遭遇故障。这将对你的站点造成严重影响,可能导致服务中断。其次,第三方镜像站可能无法及时更新和同步你的站点内容,导致访问者无法获取最新的信息。最后,自建镜像站可以让你更加灵活地定制和管理自己的站点,满足特定需求和提供更好的用户体验。因此,建议在可行的情况下,考虑自建镜像站来确保数据的安全和可靠性。</p> <p>同时,本文也适用于其他网站的镜像搭建。</p> <h2 id="方法一使用又拍云搭建"><a class="anchor" href="#方法一使用又拍云搭建">#</a> 方法一:使用又拍云搭建</h2> <h3 id="优点"><a class="anchor" href="#优点">#</a> 优点:</h3> <ol> <li>又拍云是国内知名企业级云服务商,其服务极速、稳定、简单易用,用来搭建镜像站是十分合适的。又拍云有非常多的优惠:加入又拍云联盟 (网站需备案,要在网站 / 应用底部添加又拍云 LOGO 并指向官网) 后,可以获得每月 10G 储存空间和 15G 的 CDN 流量 (按年发放,以 67 元的代金卷发放到账户);新用户注册 (<span class="exturl" data-url="aHR0cHM6Ly9jb25zb2xlLnVweXVuLmNvbS9yZWdpc3Rlci8/aW52aXRlPXRJOGxqaXhJVA==">点我注册</span>) 还可以直接获得 61 元的代金卷 (有效期一年)。在这些优惠的加成下,你可以零成本搭建一个镜像站。</li> </ol> <p>2. 加速效果明显 (如图)</p> <p>加速前:<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/blog_img_%E5%8A%A0%E9%80%9F%E5%89%8D_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/blog_img_加速前_d41d8cd98f00b204e9800998ecf8427e.png" title="加速前" /></p> <p>加速后:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/blog_img_%E5%8A%A0%E9%80%9F%E5%90%8E_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/blog_img_加速后_d41d8cd98f00b204e9800998ecf8427e.png" title="加速后" /></p> <h3 id="缺点"><a class="anchor" href="#缺点">#</a> 缺点:</h3> <p>需要备案!!!</p> <h3 id="推荐指数"><a class="anchor" href="#推荐指数">#</a> 推荐指数:⭐⭐⭐⭐⭐</h3> <h3 id="搭建方法"><a class="anchor" href="#搭建方法">#</a> 搭建方法:</h3> <h4 id="第一步"><a class="anchor" href="#第一步">#</a> 第一步:</h4> <p>创建又拍云账户 (<span class="exturl" data-url="aHR0cHM6Ly9jb25zb2xlLnVweXVuLmNvbS9yZWdpc3Rlci8/aW52aXRlPXRJOGxqaXhJVA==">点我注册</span>)</p> <h4 id="第二步"><a class="anchor" href="#第二步">#</a> 第二步:</h4> <p>进入控制台的 CDN 管理界面 (<span class="exturl" data-url="aHR0cHM6Ly9jb25zb2xlLnVweXVuLmNvbS9zZXJ2aWNlcy9jZG4v">https://console.upyun.com/services/cdn/</span>), 并创建服务,然后配置服务 (具体参数如下)。</p> <ol> <li>服务名称:唯一标识服务,例如:image-upyun-com,一个服务下面可以绑定多个自有域名。</li> </ol> <div class="note info"> <p><strong>注意事项</strong><br /> 服务名称仅限 5~20 位; 必须以小写英文字符开头,仅支持小写英文字符、数字、中划线组合。</p> </div> <ol start="2"> <li>加速域名:填写此次需要配置的加速域名。</li> </ol> <div class="note info"> <p><strong>注意事项</strong><br /> 加速域名必须已在工信部备案; 待加速域名尚未在又拍云 CDN 平台配置。</p> </div> <p>加速域名需要进行<span class="exturl" data-url="aHR0cHM6Ly9oZWxwLnVweXVuLmNvbS9rbm93bGVkZ2UtYmFzZS9kb21haW4tdmVyaWZ5Lw==">域名所有权验证</span>,验证通过后方能添加成功。</p> <ol start="3"> <li>应用场景:这里选择全站加速</li> <li>回源协议:选协议跟随。</li> <li>源站证书校验:切记!!不要打开 (实测开了以后不能用)!!!</li> <li>线路配置:源站地址填 <code>cdn.jsdelivr.net</code> , 端口号不要动。</li> </ol> <h4 id="第三步"><a class="anchor" href="#第三步">#</a> 第三步</h4> <ol> <li>服务创建成功后,操作界面会提示 CDN 加速服务创建成功,并会自动跳转到该服务的【功能配置】界面</li> <li>在功能配置界面,有域名管理、回源管理、缓存配置、性能优化、HTTPS、访问控制、图片处理等功能配置模块,在【域名管理】模块下,可以针对该服务绑定多个自有域名,请耐心等待域名配置(约 10 分钟),查看域名对应的状态是否为[正常]</li> <li>可查看 CDN 平台为您分配的 CNAME 地址,此时需要去域名 DNS 解析商处,为该域名添加一条 CNAME 记录,待 CNAME 配置生效之后,方可使用 CDN 服务。</li> </ol> <h4 id="第四步非必要但是可以提升体验"><a class="anchor" href="#第四步非必要但是可以提升体验">#</a> 第四步 (非必要,但是可以提升体验)</h4> <ol> <li> <p>配置 HTTPS: 点击 [HTTPS], 点击 &quot;HTTPS 配置&quot; 右边的管理 (如图)<img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/image_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/image_d41d8cd98f00b204e9800998ecf8427e.png" /> 然后你可以选择添加自有证书或直接使用又拍云注册证书 (<span class="exturl" data-url="aHR0cHM6Ly9jb25zb2xlLnVweXVuLmNvbS90b29sYm94L3NzbC8=">点我前往证书管理</span>)。添加完后,打开 [HTTPS 访问],不建议勾选 [强制 HTTPS 访问]。</p> </li> <li> <p>建议打开智能压缩和页面压缩 (如图)<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703354977231_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703354977231_d41d8cd98f00b204e9800998ecf8427e.png" /></p> </li> <li> <p>建议配置缓存、浏览器缓存和分段缓存 (如图)<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355090340_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355090340_d41d8cd98f00b204e9800998ecf8427e.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355115278_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355115278_d41d8cd98f00b204e9800998ecf8427e.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355198422_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355198422_d41d8cd98f00b204e9800998ecf8427e.png" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355224230_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355224230_d41d8cd98f00b204e9800998ecf8427e.png" /></p> </li> <li> <p>在 [访问控制] 中,打开 Referer 防盗链、WAF 保护、HTTP 请求体大小限制、IP 访问限制 (如图)<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355343968_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355343968_d41d8cd98f00b204e9800998ecf8427e.png" /><br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355382813_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355382813_d41d8cd98f00b204e9800998ecf8427e.png" /><br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355473637_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355473637_d41d8cd98f00b204e9800998ecf8427e.png" /><br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355505400_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703355505400_d41d8cd98f00b204e9800998ecf8427e.png" /></p> <div class="note info"> <p>此配置仅作参考,请根据实际情况进行配置!</p> </div> </li> <li> <p>你还可以配置 [边缘规则],来实现一些特殊效果。(这里不做演示)</p> </li> </ol> <h2 id="方法二使用cloudflare-workers搭建"><a class="anchor" href="#方法二使用cloudflare-workers搭建">#</a> 方法二:使用 Cloudflare workers 搭建</h2> <h3 id="优点-2"><a class="anchor" href="#优点-2">#</a> 优点:</h3> <ol> <li>简单,步骤少,加速范围广</li> <li>无需备案,加速效果较好 (如图)<br /> 加速前:<img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/blog_img_%E5%8A%A0%E9%80%9F%E5%89%8D_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/blog_img_加速前_d41d8cd98f00b204e9800998ecf8427e.png" title="加速前" /><br /> 加速后:<img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/cfwokerjsd_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/cfwokerjsd_d41d8cd98f00b204e9800998ecf8427e.png" title="加速后" /></li> <li>无费用,每天有免费额度 (每天免费 100000 个请求)</li> </ol> <h3 id="缺点-2"><a class="anchor" href="#缺点-2">#</a> 缺点:</h3> <ol> <li>部分地区访问较慢</li> <li>免费额度较少,对于访问量大的站点可能不够</li> <li>需要有一个挂在 cloudflare 的域名</li> </ol> <h3 id="推荐指数-2"><a class="anchor" href="#推荐指数-2">#</a> 推荐指数:⭐⭐⭐⭐</h3> <h3 id="搭建方法-2"><a class="anchor" href="#搭建方法-2">#</a> 搭建方法</h3> <h4 id="第一步-2"><a class="anchor" href="#第一步-2">#</a> 第一步</h4> <ol> <li>在 Cloudflare 管理面板的 [Workers 和 Pages] 栏 -&gt;[概述]-&gt;[创建应用程序]-&gt;[创建 Worker](如图)<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703396996483_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703396996483_d41d8cd98f00b204e9800998ecf8427e.png" /><br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703397051051_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703397051051_d41d8cd98f00b204e9800998ecf8427e.png" /></li> <li>随便填一个名称,点击 [部署](如图)</li> </ol> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703397134262_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703397134262_d41d8cd98f00b204e9800998ecf8427e.png" /></p> <h4 id="第二步-2"><a class="anchor" href="#第二步-2">#</a> 第二步</h4> <ol> <li>在创建完成的页面点击 [编辑代码](如图)<img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703397288998_d41d8cd98f00b204e9800998ecf8427e.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/23/12/24/1703397288998_d41d8cd98f00b204e9800998ecf8427e.png" /></li> <li>将以下代码直接粘贴进代码框:</li> </ol> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * static files (404.html, sw.js, conf.js)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">ASSET_URL</span> = <span class="string">&#x27;https://cdn.jsdelivr.net&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">JS_VER</span> = <span class="number">10</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">MAX_RETRY</span> = <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/** <span class="doctag">@type</span> &#123;<span class="type">RequestInit</span>&#125; */</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">PREFLIGHT_INIT</span> = &#123;</span><br><span class="line"> <span class="attr">status</span>: <span class="number">204</span>,</span><br><span class="line"> <span class="attr">headers</span>: <span class="keyword">new</span> <span class="title class_">Headers</span>(&#123;</span><br><span class="line"> <span class="string">&#x27;access-control-allow-origin&#x27;</span>: <span class="string">&#x27;*&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;access-control-allow-methods&#x27;</span>: <span class="string">&#x27;GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;access-control-max-age&#x27;</span>: <span class="string">&#x27;1728000&#x27;</span>,</span><br><span class="line"> &#125;),</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">any</span>&#125; <span class="variable">body</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">number</span>&#125; <span class="variable">status</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Object&lt;string, string&gt;</span>&#125; <span class="variable">headers</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">makeRes</span>(<span class="params">body, status = <span class="number">200</span>, headers = &#123;&#125;</span>) &#123;</span><br><span class="line"> headers[<span class="string">&#x27;--ver&#x27;</span>] = <span class="variable constant_">JS_VER</span></span><br><span class="line"> headers[<span class="string">&#x27;access-control-allow-origin&#x27;</span>] = <span class="string">&#x27;*&#x27;</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(body, &#123;status, headers&#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">string</span>&#125; urlStr </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">newUrl</span>(<span class="params">urlStr</span>) &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title function_">URL</span>(urlStr)</span><br><span class="line"> &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="title function_">addEventListener</span>(<span class="string">&#x27;fetch&#x27;</span>, <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> ret = <span class="title function_">fetchHandler</span>(e)</span><br><span class="line"> .<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;cfworker error:\n&#x27;</span> + err.<span class="property">stack</span>, <span class="number">502</span>))</span><br><span class="line"> e.<span class="title function_">respondWith</span>(ret)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">FetchEvent</span>&#125; e </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">fetchHandler</span>(<span class="params">e</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> req = e.<span class="property">request</span></span><br><span class="line"> <span class="keyword">const</span> urlStr = req.<span class="property">url</span></span><br><span class="line"> <span class="keyword">const</span> urlObj = <span class="keyword">new</span> <span class="title function_">URL</span>(urlStr)</span><br><span class="line"> <span class="keyword">const</span> path = urlObj.<span class="property">href</span>.<span class="title function_">substr</span>(urlObj.<span class="property">origin</span>.<span class="property">length</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (urlObj.<span class="property">protocol</span> === <span class="string">&#x27;http:&#x27;</span>) &#123;</span><br><span class="line"> urlObj.<span class="property">protocol</span> = <span class="string">&#x27;https:&#x27;</span></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;&#x27;</span>, <span class="number">301</span>, &#123;</span><br><span class="line"> <span class="string">&#x27;strict-transport-security&#x27;</span>: <span class="string">&#x27;max-age=99999999; includeSubDomains; preload&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;location&#x27;</span>: urlObj.<span class="property">href</span>,</span><br><span class="line"> &#125;)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (path.<span class="title function_">startsWith</span>(<span class="string">&#x27;/http/&#x27;</span>)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">httpHandler</span>(req, path.<span class="title function_">substr</span>(<span class="number">6</span>))</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">switch</span> (path) &#123;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">&#x27;/http&#x27;</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;请更新 cfworker 到最新版本!&#x27;</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="string">&#x27;/ws&#x27;</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;not support&#x27;</span>, <span class="number">400</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="string">&#x27;/works&#x27;</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;it works&#x27;</span>)</span><br><span class="line"> <span class="attr">default</span>:</span><br><span class="line"> <span class="comment">// static files</span></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="variable constant_">ASSET_URL</span> + path)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Request</span>&#125; <span class="variable">req</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">string</span>&#125; <span class="variable">pathname</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">httpHandler</span>(<span class="params">req, pathname</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> reqHdrRaw = req.<span class="property">headers</span></span><br><span class="line"> <span class="keyword">if</span> (reqHdrRaw.<span class="title function_">has</span>(<span class="string">&#x27;x-jsproxy&#x27;</span>)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title class_">Response</span>.<span class="title function_">error</span>()</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// preflight</span></span><br><span class="line"> <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;OPTIONS&#x27;</span> &amp;&amp;</span><br><span class="line"> reqHdrRaw.<span class="title function_">has</span>(<span class="string">&#x27;access-control-request-headers&#x27;</span>)</span><br><span class="line"> ) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, <span class="variable constant_">PREFLIGHT_INIT</span>)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> acehOld = <span class="literal">false</span></span><br><span class="line"> <span class="keyword">let</span> rawSvr = <span class="string">&#x27;&#x27;</span></span><br><span class="line"> <span class="keyword">let</span> rawLen = <span class="string">&#x27;&#x27;</span></span><br><span class="line"> <span class="keyword">let</span> rawEtag = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> reqHdrNew = <span class="keyword">new</span> <span class="title class_">Headers</span>(reqHdrRaw)</span><br><span class="line"> reqHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;x-jsproxy&#x27;</span>, <span class="string">&#x27;1&#x27;</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 此处逻辑和 http-dec-req-hdr.lua 大致相同</span></span><br><span class="line"> <span class="comment">// https://github.com/EtherDream/jsproxy/blob/master/lua/http-dec-req-hdr.lua</span></span><br><span class="line"> <span class="keyword">const</span> refer = reqHdrNew.<span class="title function_">get</span>(<span class="string">&#x27;referer&#x27;</span>)</span><br><span class="line"> <span class="keyword">const</span> query = refer.<span class="title function_">substr</span>(refer.<span class="title function_">indexOf</span>(<span class="string">&#x27;?&#x27;</span>) + <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">if</span> (!query) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;missing params&#x27;</span>, <span class="number">403</span>)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">const</span> param = <span class="keyword">new</span> <span class="title class_">URLSearchParams</span>(query)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">const</span> [k, v] <span class="keyword">of</span> <span class="title class_">Object</span>.<span class="title function_">entries</span>(param)) &#123;</span><br><span class="line"> <span class="keyword">if</span> (k.<span class="title function_">substr</span>(<span class="number">0</span>, <span class="number">2</span>) === <span class="string">&#x27;--&#x27;</span>) &#123;</span><br><span class="line"> <span class="comment">// 系统信息</span></span><br><span class="line"> <span class="keyword">switch</span> (k.<span class="title function_">substr</span>(<span class="number">2</span>)) &#123;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">&#x27;aceh&#x27;</span>:</span><br><span class="line"> acehOld = <span class="literal">true</span></span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> <span class="keyword">case</span> <span class="string">&#x27;raw-info&#x27;</span>:</span><br><span class="line"> [rawSvr, rawLen, rawEtag] = v.<span class="title function_">split</span>(<span class="string">&#x27;|&#x27;</span>)</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">// 还原 HTTP 请求头</span></span><br><span class="line"> <span class="keyword">if</span> (v) &#123;</span><br><span class="line"> reqHdrNew.<span class="title function_">set</span>(k, v)</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> reqHdrNew.<span class="title function_">delete</span>(k)</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!param.<span class="title function_">has</span>(<span class="string">&#x27;referer&#x27;</span>)) &#123;</span><br><span class="line"> reqHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;referer&#x27;</span>)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// cfworker 会把路径中的 `//` 合并成 `/`</span></span><br><span class="line"> <span class="keyword">const</span> urlStr = pathname.<span class="title function_">replace</span>(<span class="regexp">/^(https?):\/+/</span>, <span class="string">&#x27;$1://&#x27;</span>)</span><br><span class="line"> <span class="keyword">const</span> urlObj = <span class="title function_">newUrl</span>(urlStr)</span><br><span class="line"> <span class="keyword">if</span> (!urlObj) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;invalid proxy url: &#x27;</span> + urlStr, <span class="number">403</span>)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/** <span class="doctag">@type</span> &#123;<span class="type">RequestInit</span>&#125; */</span></span><br><span class="line"> <span class="keyword">const</span> reqInit = &#123;</span><br><span class="line"> <span class="attr">method</span>: req.<span class="property">method</span>,</span><br><span class="line"> <span class="attr">headers</span>: reqHdrNew,</span><br><span class="line"> <span class="attr">redirect</span>: <span class="string">&#x27;manual&#x27;</span>,</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;POST&#x27;</span>) &#123;</span><br><span class="line"> reqInit.<span class="property">body</span> = req.<span class="property">body</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">proxy</span>(urlObj, reqInit, acehOld, rawLen, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">URL</span>&#125; urlObj </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">RequestInit</span>&#125; reqInit </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">number</span>&#125; retryTimes </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">proxy</span>(<span class="params">urlObj, reqInit, acehOld, rawLen, retryTimes</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">fetch</span>(urlObj.<span class="property">href</span>, reqInit)</span><br><span class="line"> <span class="keyword">const</span> resHdrOld = res.<span class="property">headers</span></span><br><span class="line"> <span class="keyword">const</span> resHdrNew = <span class="keyword">new</span> <span class="title class_">Headers</span>(resHdrOld)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> expose = <span class="string">&#x27;*&#x27;</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">const</span> [k, v] <span class="keyword">of</span> resHdrOld.<span class="title function_">entries</span>()) &#123;</span><br><span class="line"> <span class="keyword">if</span> (k === <span class="string">&#x27;access-control-allow-origin&#x27;</span> ||</span><br><span class="line"> k === <span class="string">&#x27;access-control-expose-headers&#x27;</span> ||</span><br><span class="line"> k === <span class="string">&#x27;location&#x27;</span> ||</span><br><span class="line"> k === <span class="string">&#x27;set-cookie&#x27;</span></span><br><span class="line"> ) &#123;</span><br><span class="line"> <span class="keyword">const</span> x = <span class="string">&#x27;--&#x27;</span> + k</span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(x, v)</span><br><span class="line"> <span class="keyword">if</span> (acehOld) &#123;</span><br><span class="line"> expose = expose + <span class="string">&#x27;,&#x27;</span> + x</span><br><span class="line"> &#125;</span><br><span class="line"> resHdrNew.<span class="title function_">delete</span>(k)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (acehOld &amp;&amp;</span><br><span class="line"> k !== <span class="string">&#x27;cache-control&#x27;</span> &amp;&amp;</span><br><span class="line"> k !== <span class="string">&#x27;content-language&#x27;</span> &amp;&amp;</span><br><span class="line"> k !== <span class="string">&#x27;content-type&#x27;</span> &amp;&amp;</span><br><span class="line"> k !== <span class="string">&#x27;expires&#x27;</span> &amp;&amp;</span><br><span class="line"> k !== <span class="string">&#x27;last-modified&#x27;</span> &amp;&amp;</span><br><span class="line"> k !== <span class="string">&#x27;pragma&#x27;</span></span><br><span class="line"> ) &#123;</span><br><span class="line"> expose = expose + <span class="string">&#x27;,&#x27;</span> + k</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (acehOld) &#123;</span><br><span class="line"> expose = expose + <span class="string">&#x27;,--s&#x27;</span></span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--t&#x27;</span>, <span class="string">&#x27;1&#x27;</span>)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// verify</span></span><br><span class="line"> <span class="keyword">if</span> (rawLen) &#123;</span><br><span class="line"> <span class="keyword">const</span> newLen = resHdrOld.<span class="title function_">get</span>(<span class="string">&#x27;content-length&#x27;</span>) || <span class="string">&#x27;&#x27;</span></span><br><span class="line"> <span class="keyword">const</span> badLen = (rawLen !== newLen)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (badLen) &#123;</span><br><span class="line"> <span class="keyword">if</span> (retryTimes &lt; <span class="variable constant_">MAX_RETRY</span>) &#123;</span><br><span class="line"> urlObj = <span class="keyword">await</span> <span class="title function_">parseYtVideoRedir</span>(urlObj, newLen, res)</span><br><span class="line"> <span class="keyword">if</span> (urlObj) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">proxy</span>(urlObj, reqInit, acehOld, rawLen, retryTimes + <span class="number">1</span>)</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">makeRes</span>(res.<span class="property">body</span>, <span class="number">400</span>, &#123;</span><br><span class="line"> <span class="string">&#x27;--error&#x27;</span>: <span class="string">`bad len: <span class="subst">$&#123;newLen&#125;</span>, except: <span class="subst">$&#123;rawLen&#125;</span>`</span>,</span><br><span class="line"> <span class="string">&#x27;access-control-expose-headers&#x27;</span>: <span class="string">&#x27;--error&#x27;</span>,</span><br><span class="line"> &#125;)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (retryTimes &gt; <span class="number">1</span>) &#123;</span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--retry&#x27;</span>, retryTimes)</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> status = res.<span class="property">status</span></span><br><span class="line"></span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;access-control-expose-headers&#x27;</span>, expose)</span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;access-control-allow-origin&#x27;</span>, <span class="string">&#x27;*&#x27;</span>)</span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--s&#x27;</span>, status)</span><br><span class="line"> resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--ver&#x27;</span>, <span class="variable constant_">JS_VER</span>)</span><br><span class="line"></span><br><span class="line"> resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy&#x27;</span>)</span><br><span class="line"> resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy-report-only&#x27;</span>)</span><br><span class="line"> resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;clear-site-data&#x27;</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (status === <span class="number">301</span> ||</span><br><span class="line"> status === <span class="number">302</span> ||</span><br><span class="line"> status === <span class="number">303</span> ||</span><br><span class="line"> status === <span class="number">307</span> ||</span><br><span class="line"> status === <span class="number">308</span></span><br><span class="line"> ) &#123;</span><br><span class="line"> status = status + <span class="number">10</span></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(res.<span class="property">body</span>, &#123;</span><br><span class="line"> status,</span><br><span class="line"> <span class="attr">headers</span>: resHdrNew,</span><br><span class="line"> &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">URL</span>&#125; urlObj </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">isYtUrl</span>(<span class="params">urlObj</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> urlObj.<span class="property">host</span>.<span class="title function_">endsWith</span>(<span class="string">&#x27;.googlevideo.com&#x27;</span>) &amp;&amp;</span><br><span class="line"> urlObj.<span class="property">pathname</span>.<span class="title function_">startsWith</span>(<span class="string">&#x27;/videoplayback&#x27;</span>)</span><br><span class="line"> )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">URL</span>&#125; urlObj </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">number</span>&#125; newLen </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Response</span>&#125; res </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">parseYtVideoRedir</span>(<span class="params">urlObj, newLen, res</span>) &#123;</span><br><span class="line"> <span class="keyword">if</span> (newLen &gt; <span class="number">2000</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="title function_">isYtUrl</span>(urlObj)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> data = <span class="keyword">await</span> res.<span class="title function_">text</span>()</span><br><span class="line"> urlObj = <span class="keyword">new</span> <span class="title function_">URL</span>(data)</span><br><span class="line"> &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="title function_">isYtUrl</span>(urlObj)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> urlObj</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p> <p>3. 点击 [保存并部署]。</p> <h4 id="第三步-2"><a class="anchor" href="#第三步-2">#</a> 第三步</h4> <p>回到 [概述],点击你刚才创建的项目,点击 [触发器],点击 [添加自定义域],填入一个你账户中的域名或其子域名,点击 [添加自定义域],完成搭建。</p> <h2 id="方法三使用deno-playground搭建"><a class="anchor" href="#方法三使用deno-playground搭建">#</a> 方法三:使用 Deno Playground 搭建</h2> <h3 id="优点-3"><a class="anchor" href="#优点-3">#</a> 优点:</h3> <ol> <li>配置十分简单,加速范围广</li> <li>无需备案,加速效果较好 (如图)<br /> 加速前:<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_ee2ba28d08999e625e9e68716f43db68.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_ee2ba28d08999e625e9e68716f43db68.png" /><br /> 加速后:<br /> <img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_dc2d54ac2088cec188556bc6e5582c9a.png" alt="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_dc2d54ac2088cec188556bc6e5582c9a.png" title="加速后" /></li> <li>免费额度多,每月 1000000 次请求,100G 流量</li> <li>只要 DNS 解析就行,不用像 Cloudflare 一样需要修改域名 NS</li> </ol> <h3 id="缺点-3"><a class="anchor" href="#缺点-3">#</a> 缺点:</h3> <ol> <li>部分地区访问较慢</li> <li>没有攻击防护和其他安全功能,存在被攻击或刷流量的风险</li> <li>官方自带的域名被墙,需要自备域名</li> </ol> <h3 id="推荐指数-3"><a class="anchor" href="#推荐指数-3">#</a> 推荐指数:⭐⭐⭐⭐⭐</h3> <h3 id="搭建方法-3"><a class="anchor" href="#搭建方法-3">#</a> 搭建方法</h3> <h4 id="第一步-3"><a class="anchor" href="#第一步-3">#</a> 第一步</h4> <ol> <li> <p>登录后,在主页右上角点击 [New Playground]</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_df83a1d70d519c100210e71c5aec864d.png" alt="" /></p> </li> <li> <p>进入代码编辑页面:</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_6b286fe6d87f51dc041d9bf86b27acd7.png" alt="" /><br /> 如果你没有进入此页面,也可以在主页找到你创建的项目,点击 [Playground] 进入编辑</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_d8d0b8aecb44e3d7631f209870cf5a88.png" alt="" /></p> </li> </ol> <h4 id="第二步-3"><a class="anchor" href="#第二步-3">#</a> 第二步</h4> <p>将以下代码直接粘贴进代码框:</p> <p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="variable constant_">HOST</span> = <span class="string">&quot;fastly.jsdelivr.net&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Deno</span>.<span class="title function_">serve</span>(<span class="title function_">async</span> (request) =&gt; &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>);</span><br><span class="line"></span><br><span class="line">url.<span class="property">host</span> = <span class="variable constant_">HOST</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> newRequest = <span class="keyword">new</span> <span class="title class_">Request</span>(url.<span class="title function_">toString</span>(), &#123;</span><br><span class="line"></span><br><span class="line"><span class="attr">headers</span>: request.<span class="property">headers</span>,</span><br><span class="line"></span><br><span class="line"><span class="attr">method</span>: request.<span class="property">method</span>,</span><br><span class="line"></span><br><span class="line"><span class="attr">body</span>: request.<span class="property">body</span>,</span><br><span class="line"></span><br><span class="line"><span class="attr">redirect</span>: <span class="string">&quot;follow&quot;</span>,</span><br><span class="line"></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">await</span> <span class="title function_">fetch</span>(newRequest);</span><br><span class="line"></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></p> <p>3. 点击 [Save &amp; Deploy]。</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_413cb7fc502499db25d9dcdbbfc72fc8.png" alt="" /></p> <h4 id="第三步-3"><a class="anchor" href="#第三步-3">#</a> 第三步</h4> <p>回到你的项目管理页面,点击 [Settings],点击 [Domains],再点击 [Add Domain],填入一个你的域名或其子域名,点击 [Setup], 按照指示完成 DNS 解析后,点击 [Validate], 并点击自动配置证书,完成搭建。(下方有示例图)</p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_ebbd1ba342ad1fff1c83ec3404755559.png" alt="" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_d9c4095ac6c21865fc773e2bcca5e5f6.png" alt="" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_9fda6e5f7ae41060e59b3cc092bc552d.png" alt="" /></p> <p><img data-src="https://upcdn.jdjwzx233.cn/upload/Qexo/25/5/4/image_80297be1451d4fb7c0e47e581267e4f0.png" alt="" /></p> <h2 id="方法四使用nginx"><a class="anchor" href="#方法四使用nginx">#</a> 方法四:使用 nginx</h2> <h3 id="优点简单"><a class="anchor" href="#优点简单">#</a> 优点:简单</h3> <h3 id="缺点-4"><a class="anchor" href="#缺点-4">#</a> 缺点:</h3> <p>加速范围不广,速度受到服务器性能和速度限制。</p> <h3 id="推荐指数-4"><a class="anchor" href="#推荐指数-4">#</a> 推荐指数:⭐⭐⭐</h3> <p>新建一个网站,然后把下面内容覆盖到 nginx 配置文件</p> <p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line"></span><br><span class="line"> listen 80;</span><br><span class="line"></span><br><span class="line"> listen 443 ssl http2;</span><br><span class="line"></span><br><span class="line"> # 请更改为你的证书路径</span><br><span class="line"> ssl_certificate fullchain.pem;</span><br><span class="line"> ssl_certificate_key privkey.pem;</span><br><span class="line"></span><br><span class="line"> # 请更改为你的镜像域名</span><br><span class="line"> server_name jsd.ucbk.cn;</span><br><span class="line"></span><br><span class="line"> location / &#123;</span><br><span class="line"> proxy_pass https://cdn.jsdelivr.net;</span><br><span class="line"> proxy_set_header Host $proxy_host;</span><br><span class="line"> proxy_set_header Accept-Encoding &#x27;&#x27;;</span><br><span class="line"> proxy_ssl_server_name on;</span><br><span class="line"> proxy_ssl_name $proxy_host;</span><br><span class="line"> proxy_redirect / /;</span><br><span class="line"> # Proxy Cache</span><br><span class="line"> proxy_cache jsdelivr;</span><br><span class="line"> proxy_cache_lock on;</span><br><span class="line"> proxy_cache_lock_timeout 15s;</span><br><span class="line"> proxy_cache_use_stale updating;</span><br><span class="line"> proxy_cache_background_update on;</span><br><span class="line"> proxy_cache_key $host$request_uri;</span><br><span class="line"> proxy_cache_valid 200 301 302 30d;</span><br><span class="line"> proxy_cache_valid 500 501 502 503 15s;</span><br><span class="line"> proxy_cache_valid any 5m;</span><br><span class="line"> # Replace Domain</span><br><span class="line"> sub_filter_once off;</span><br><span class="line"> sub_filter_types application/javascript application/json text/xml text/css;</span><br><span class="line"> sub_filter &#x27;$proxy_host&#x27; &#x27;$host&#x27;;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"># 缓存路径请根据需要更改</span><br><span class="line">proxy_cache_path /var/tmp/nginx/jsdelivr levels=1:2 use_temp_path=off keys_zone=jsdelivr:300m inactive=30d max_size=30g;</span><br></pre></td></tr></table></figure></p> <p>之后直接把网站涉及到 <code>cdn.jsdelivr.net</code> 都改成你自己的就可以了,如果不想改的话直接在你网站 nginx 配置中加以下内容就可以了</p> <p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sub_filter_once off;</span><br><span class="line">sub_filter_types application/javascript application/json text/xml text/css;</span><br><span class="line">sub_filter &#x27;cdn.jsdelivr.net&#x27; &#x27;jsd.ucbk.cn&#x27;;</span><br></pre></td></tr></table></figure></p> <h2 id="结尾"><a class="anchor" href="#结尾">#</a> 结尾</h2> <p>除了上述的服务之外,还有其他同样优秀的云服务商可以用于搭建镜像,如腾讯云、阿里云等等,但都存在一个致命的问题:需要备案。希望本文提供的方法可以帮到你,你同样也可以将这个方法用在其他网站的镜像上 (只需要修改一下代码就行)</p> <p>博主已经搭建了一个镜像站:</p> <p><span class="exturl" data-url="aHR0cHM6Ly9teXN0aWNnbG93LmRwZG5zLm9yZw==">mysticglow.dpdns.org</span></p> <p>这个镜像站目前还没被墙,如有需要的,可以拿去使用,这个镜像站每个月只有 100 万次请求数和 100G 的流量,如果可以的话请自行搭建,不会或懒得搭建的可以使用本站的 (๑・ᴗ・๑)♡</p> <p>非常感谢你能看到这里,如有什么问题欢迎在评论区中提出!<br /> 如果你觉得我的博客不错的话,可以赞助我 (・̀ ω・́)✧:</p> <p><a href="https://jdjwzx233.cn/support" title="赞助我吧,要饿死了QWQ">https://jdjwzx233.cn/support</a>。</p>

2023/12/23
阅读更多

Edge在保留数据的情况下退出微软账户登录

<p>现在,越来越多的人使用 Edge 浏览器来进行网络浏览,但有时候您可能需要退出微软账户登录。问题是,当您退出时,您是否会失去本地存储设备上的数据?本文将解答您的疑惑,告诉您如何在退出微软账户前保留本地数据。</p> <h2 id="正文"><a class="anchor" href="#正文">#</a> 正文</h2> <p>当我们无法登录账户时,如果要在 Edge 中退出微软账户登录,可能需要进入该账户的主页才能退出,否则只能使用删除该用户配置才可退出,但这会导致数据丢失,并使一些平台需要重新登录,非常的不方便。</p> <p>但是,我们可以使用一些其他的方法保留数据退出登录。</p> <p>在 Windows 的资源管理器中,找到你的用户数据文件夹 (正常情况都在这里)。</p> <p><code>C:\Users\用户名\AppData\Local\Microsoft\Edge\User Data</code></p> <p>一般来说,你的数据都存储在 Default 文件夹中,如图:</p> <p><img data-src="https://images.jdjwzx233.cn/upload/Qexo/2023/6/26/image_901d395526eefaf6e30a26fdc9a90d16.png" alt="https://images.jdjwzx233.cn/upload/Qexo/2023/6/26/image_901d395526eefaf6e30a26fdc9a90d16.png" /></p> <p>但是有时候你使用了其他用户配置,那么你的数据可能在 <code>Profile+数字</code> 文件夹中,这个要根据你的实际情况进行选择。</p> <div class="note danger"> <p>注意!以下操作可能会导致数据丢失,请提前备份好相关数据,再进行操作!</p> </div> <p>当你找到自己的数据文件夹后,你需要关闭 Edge 浏览器,注意!要到 <code>任务管理器</code> 中关闭,直接关闭是无效的。</p> <p>关闭后,你需要备份这个文件夹,完成后,你就可以开始进行退出登录的操作了。</p> <p>在你的文件夹中,找到这几个文件,如图:</p> <p><img data-src="https://images.jdjwzx233.cn/upload/Qexo/2023/6/25/image_4a0ce70e5fa19687d509e4752fdb97af.png" alt="https://image.jdjwzx233.cn/upload/Qexo/2023/6/25/image_4a0ce70e5fa19687d509e4752fdb97af.png" /></p> <div class="note warning"> <p>以下操作可能会使你保存的密码全部丢失,请提前到设置中导出密码,再进行本操作,导入导出密码的教程放在文章结尾。</p> </div> <p>然后删除 <code>Preferences</code> , <code>Login Data-journal</code> , <code>Login Data</code> 这三个文件。回到浏览器后,你会发现,你的数据还在,但你的账户被退出了。</p> <p>在登录你的微软账号后,你就可以导入原来的密码,完成这步后,那么恭喜你,你已经成功完成了退出微软账户保留本地数据的操作!</p> <h2 id="转移数据"><a class="anchor" href="#转移数据">#</a> 转移数据</h2> <p>本方法同样适用于转移数据,你只需要将需要转移的用户文件夹中的内容,复制替换掉新的用户文件夹中的内容即可,在此操作之前,你需要备份被替换的用户文件夹中 <code>Preferences</code> , <code>Login Data-journal</code> , <code>Login Data</code> 这三个文件,在完成数据转移后,再移动回来,这样,你就完成了数据转移。</p> <h3 id="导出或导入密码"><a class="anchor" href="#导出或导入密码">#</a> 导出或导入密码</h3> <p>首先,打开 <code>Edge://settings/passwords</code> 或者你可以打开 <code>设置</code> -&gt; <code>个人资料</code> -&gt; <code>密码</code> 。</p> <p>然后,在这个地方点击右边的三个点,如图:</p> <p><img data-src="https://images.jdjwzx233.cn/upload/Qexo/2023/6/26/image_1c76ad526b021903d93f8f1a5a944e60.png" alt="https://images.jdjwzx233.cn/upload/Qexo/2023/6/26/image_1c76ad526b021903d93f8f1a5a944e60.png" /></p> <p>选择 <code>导出密码</code> ,在进行这一步时,你可能需要验证你的身份,按照步骤来就行。</p> <p>最后,将你的密码保存到一个安全的地方,后面导入密码时,同样也是在此地方进行。<br /> 如果你觉得我的博客不错的话,可以赞助我 (・̀ ω・́)✧:<a href="https://jdjwzx233.cn/support">https://jdjwzx233.cn/support</a>。</p>

2023/6/25
阅读更多

优秀作文分享——人间烟雨,感谢有你

<p>烟雨迷蒙,如同人生。回首往事,最难忘却的莫过于与你相遇时的情景了吧!—— 题记</p> <p>烟雨中的你是否还记得那一抹清丽的身影?这个女孩子很特别,她不像其他小姑娘一样喜欢花裙子和洋娃娃,而更爱穿着布鞋踏遍青石板路上的每一处角落。</p> <p>只因为从前年幼无知的我们都曾经问过彼此:“妈妈说下雨天地面湿滑会摔跤,可以光脚走吗?” 看到大家齐刷刷摇头后便兴高采烈地脱掉了凉鞋,赤足跑进水坑或泥泞里玩耍去了…… 渐渐长大后才明白当初母亲微笑背后的苦涩心酸,也终于理解了你对我们所谓 “放养式教育” 的坚持。</p> <p>多么希望能够再次见到你啊!但愿岁月静好,现世安稳。 在我眼里,你就是仙女姐姐般美好纯洁的存在,你总是用温柔细腻的手抚摸着我们受伤的心灵,告诉我们要勇敢、乐观地活出精彩。</p> <p>即使偶尔发脾气,嘴巴也依旧甜甜软软的。我想你应该永远是那副没什么烦恼的模样吧,虽然我们之间隔着千山万水,但我始终觉得你离我并不遥远。尽管我们素未谋面,甚至连声音都听不真切,但仿佛冥冥之中早已注定,我们将会成为最熟悉的陌生人。</p> <p>直到今日我仍深信缘分二字,命运让我们相识又让我们重逢,这种感觉实在太奇妙了。</p> <p>“有朋自远方来,不亦乐乎”。古人诚不欺我,每当收到你寄来的贺卡,打开它时内心的欣喜溢于言表;翻阅它时脑海中浮现的画面似电影般闪过;合起它时鼻尖萦绕的香味久久挥散不去… 待我读懂了你的文字,品尝了你送给我的巧克力糖果,体验了你讲述的动人故事,享受了你赠予我的珍贵礼物,聆听了你传授的宝贵经验,我恍然顿悟原来我们的相遇竟是命中注定。如若不是在茫茫人海中邂逅,怎会碰撞出绚烂火花?倘若不是被你治愈了伤痛,怎会触及到柔软的内心?谢谢你,带给我的点滴暖意;谢谢你,陪伴我度过的漫长旅程;谢谢你,让我学会了坦然释怀;谢谢你,令我变得越来越优秀。</p> <p>烟雨朦胧,梦境斑驳,轻捻指尖,满目芬芳。烟雨中的你,是否还记得我呢?我期盼着,下一场烟雨,我们能再次相约。</p>

2023/1/28
阅读更多

优秀作文分享——从未走远

<p>我们从未走远,只是你没发现而已。—— 题记</p> <p>一个人的心中有多少秘密?谁也无法知道,就像这世界上永远都会存在着许多令人费解之谜一样,它总是让那些充满智慧与灵感的人去猜测、探索和研究。但他们却始终得不到真正的答案。或许,每当夜深人静时,思绪便开始飞扬了吧!</p> <p>于是,所谓的诗情画意,便油然而生;所谓的浪漫气息,亦由此而来…… 于是乎,古往今来,凡大家名流,皆如痴似醉地沉浸其间。对于爱情,更是乐此不疲,因为美丽的故事总能打动人心,给予读者以无限遐想空间。 “最好不相见,免得我牵念”,唐朝才子元稹写下了千古绝唱《离思》。王维用笔墨将红豆寄托出相思之苦,李商隐则借芭蕉抒怀别恨。屈原哀叹自己遭谗被疏,伍子胥含泪鞭尸,苏轼愁断肝肠,陆游悲痛欲绝。</p> <p>明月照亮了黑暗,星光点缀了寂寞,文字带来了希望,纸张承载了梦想。文学作品里蕴藏着太多的内涵,需要细细揣摩,慢慢体味。<br /> 尽管岁月悠长,风尘渐起,惟愿历史的车轮碾过后,还留下几颗闪烁的珍珠供后人欣赏玩味。蓦然回首,青春年华早已逝去,伴随成长的足迹踏遍万水千山。可惜韶华易老,昔日容颜不再。 曾经沧海难为水,除却巫山不是云。纵使身处闹市,又怎敌得过高山流水遇知音的旷达胸襟呢?</p> <p>虽说花开堪折直须折,莫待无花空折枝。然而人非草木孰能无情?面对眼前的诱惑,恐怕很难把持住自己,甚至迷失方向。尤其是看惯了灯红酒绿的繁华景象,听够了莺歌燕舞的靡靡之音,享受惯了富贵荣华的锦衣玉食,接触多了形形色色的社会百态,岂能不贪恋权势金钱?试问:哪位君主甘愿做平民百姓?即使退一步讲,倘若抛弃了功名利禄,选择归隐田园,那么就必定淡泊名利吗?显然并非如此。</p> <p>陶渊明辞官归隐,采菊东篱下,悠然见南山,依旧钟情于 “结庐在人境,而无车马喧” 的闲适恬淡。周敦颐厌恶官场,宁愿隐居西湖孤山,仍保持清白廉洁的节操。欧阳修贬谪滁州,饱尝艰辛困顿,仍坚守信念,矢志不渝,毫不改变初衷。… 数不胜数,比比皆是。</p>

2023/1/28
阅读更多

优秀作文分享——我,在浙里

<h2 id="第一篇"><a class="anchor" href="#第一篇">#</a> 第一篇:</h2> <p>浙江,是一片神奇美丽的土地;浙江,孕育了中华民族灿烂悠久的文明;浙江,承载着数以亿计的浙商走向世界!</p> <p>“三十功名尘与土,八千里路云和月”。一首《满江红》道出了岳飞壮志难酬、报国无门的悲愤心情。但他没有被挫折所压倒,反而更加坚定自己的信念 —— 收复失地,还于旧都。在历史上留下了浓墨重彩的一笔。</p> <p>“位卑未敢忘忧国”。身为汉臣却始终忠心耿耿,宁死也要捍卫祖国领土完整。我想到了周恩来总理。他曾说过:“为中华崛起而读书!” 就是凭借这种强烈的爱国精神,才使得那么多仁人志士投入革命洪流,推翻黑暗统治,建立新中国!</p> <p>“先天下之忧而忧,后天下之乐而乐”。范仲淹从小便怀抱远大理想,立志成为像孔子一般博学多识、胸怀天下苍生的圣贤。正因此,他能够舍弃高官厚禄,毅然决然地辞职回乡,开启了著名的 “庆历新政”。虽然最终因保守势力太强而失败,但其忧国忧民的思想却永垂青史。</p> <p>“居庙堂之高则忧其君,处江湖之远则忧其民”。范仲淹两度遭贬,依然关注百姓疾苦,体恤黎民百姓。在他看来,只有让老百姓安居乐业,社会才能稳定发展。</p> <p>古人云:“读万卷书不如行千里路。” 不错,纸上谈兵并非真英雄。真正的勇者应当深入实践,躬亲实干。“宝剑锋从磨砺出,梅花香自苦寒来”。鲁迅先生把握住了知识分子的特点,用手中的笔作武器,唤醒麻木的国民。他写杂文,抨击封建制度的弊端,揭露军阀混战的罪恶;他写小说,描绘人民群众受压迫、受剥削的惨状,表现对劳动人民的同情和热爱。鲁迅先生用自己犀利的笔尖戳破假面具,撕去画皮,将丑陋的灵魂暴露给世人。他的每篇杂文犹如匕首,刺痛敌人的心脏。鲁迅先生毫不畏惧,奋斗一生,为后人树立了榜样。</p> <p>我们生活在这样一个伟大的时代,感谢科技进步带来的方便快捷。我们拥有丰富的物质财富,可以享受电影院、健身房等娱乐设施。但是,别忘记,今日的幸福生活离不开前辈们披荆斩棘的努力拼搏。我相信,在党的领导下,我们必将创造属于我们的辉煌!</p> <h2 id="第二篇"><a class="anchor" href="#第二篇">#</a> 第二篇:</h2> <p>浙里,我在这里。我来自浙南的温州,因为那儿有最美丽的海滨城市 —— 厦门;也许你会问:“怎么没有听说过‘东方夏威夷’呢?” 不错,它就是福建省第二大岛 —— 平潭县。而我们今天要去游览的则是被称之为 “小上海” 的浙江省会 --- 杭州。</p> <p>浙江是一个人杰地灵的好地方,孕育了无数名扬四海的文化巨匠和商业奇才,还造就了灿若星辰的艺术瑰宝!古代中国有四大发明,其中三项便产生于此,可见她对世界所做出的贡献之伟大啊!</p> <p>如果说北京是帝王将相聚集的地方,那么杭州绝对是富家子弟云集的场所。想当年,乾隆皇帝下江南时曾到过此处,并留下了千古佳句:“江南忆,最忆是杭州”。由此可以看出,杭州是多么令人向往与憧憬呀! “日出江花红胜火,春来江水绿如蓝”,从诗中描绘的情境可知,春季的杭州正值桃李芬芳,鸟语花香的好时节。但作者却只用了两句话概括了整个杭州的特点,让读者更加感受到了杭州的魅力与神韵。或许,每个人都有属于他(她)心目中的杭州吧!</p> <p>杭州西湖景色秀丽、山清水秀,素有 “人间天堂” 的美誉。尤其是湖中央的三座小岛 - - 小瀛洲、湖心亭和阮公墩,各具风姿。</p> <p>小瀛洲面积较大,岛上遍植花木,环境幽静。湖心亭是西湖中赏荷观鱼的最佳处,岛上建筑精巧别致,有水中仙子的雅号。阮公墩虽然面积比前两个小岛略小些,但却十分别致,登高远眺,西湖全景尽收眼底…… 傍晚,夕阳斜照在西湖上,映着波光粼粼的湖面,闪烁着金光,仿佛给湖面铺上了一层碎金似的,煞是耀眼夺目。微风吹拂着柳树,使它轻轻摇摆起来,像是姑娘们甩动长发跳舞一般,婀娜多姿,楚楚动人。夜幕降临后,月亮升空,皎洁的月光倾泻而下,洒落在湖面上,泛起阵阵银白色的涟漪,宛如仙女散花,又犹如牛郎织女隔河相望,真是妙趣横生!倘若遇到皓月当空,繁星满天的夜晚,坐在船头仰望苍穹,定能领悟到苏轼《水调歌头》中所写道的 “欲把西湖比西子,淡妆浓抹总相宜” 的意蕴吧!</p>

2023/1/26
阅读更多

将ChatGPT部署到网站上

<p>ChatGPT 是一个用于自然语言对话的预训练语言模型。要将 ChatGPT 部署到网站上,你需要执行以下步骤:</p> <ol> <li>下载 ChatGPT 模型:你可以从 Hugging Face 的 Transformers 库中下载 ChatGPT 模型。</li> <li>使用 Python 的 Flask 库创建一个 Web 应用程序。Flask 是一种轻量级的 Web 应用框架,可以让你快速构建 Web 应用程序。</li> <li>在 Web 应用中加载 ChatGPT 模型:在 Web 应用程序中,你可以使用 Transformers 库中的 <code>AutoModelWithLMHead</code> 类加载 ChatGPT 模型。</li> <li>创建一个 HTML 表单,允许用户输入对话文本。</li> <li>使用 ChatGPT 模型对用户输入的文本进行响应:当用户提交表单时,你可以使用 ChatGPT 模型的 <code>generate</code> 方法生成响应文本。</li> </ol> <p>以下是一个简单的例子,展示了如何使用 Flask 和 ChatGPT 构建一个简单的 Web 应用程序:</p> <p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, render_template, request</span><br><span class="line"><span class="keyword">from</span> transformers <span class="keyword">import</span> AutoModelWithLMHead, AutoTokenizer</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加载ChatGPT模型</span></span><br><span class="line">model = AutoModelWithLMHead.from_pretrained(<span class="string">&quot;microsoft/DialoGPT-small&quot;</span>)</span><br><span class="line">tokenizer = AutoTokenizer.from_pretrained(<span class="string">&quot;microsoft/DialoGPT-small&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&quot;/&quot;</span>, methods=[<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;POST&quot;</span>]</span>)</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">index</span>():</span><br><span class="line"> <span class="keyword">if</span> request.method == <span class="string">&quot;POST&quot;</span>:</span><br><span class="line"> <span class="comment"># 获取用户输入的文本</span></span><br><span class="line"> input_text = request.form[<span class="string">&quot;input_text&quot;</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 使用ChatGPT模型生成响应文本</span></span><br><span class="line"> prompt = (input_text, <span class="string">&quot;&quot;</span>)</span><br><span class="line"> response = model.generate(prompt, max_length=<span class="number">1024</span>, do_sample=<span class="literal">True</span>, temperature=<span class="number">0.7</span>)</span><br><span class="line"> response_text = tokenizer.decode(response[<span class="number">0</span>], skip_special_tokens=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> render_template(<span class="string">&quot;index.html&quot;</span>, response_text=response_text)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">return</span> render_template(<span class="string">&quot;index.html&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line"> app.run()</span><br></pre></td></tr></table></figure></p> <p>在这段代码中,我们使用了 Flask 的 <code>render_template</code> 函数来渲染一个 HTML 模板,并将响应文本传递给模板。我们还使用了 Transformers 库中的 <code>AutoTokenizer</code> 类来将响应文本解码为可读的文本。</p> <p>下面是一个简单的 HTML 模板,你可以使用它来显示用户输入和 ChatGPT 响应:</p> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">title</span>&gt;</span>ChatGPT Demo<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">form</span> <span class="attr">method</span>=<span class="string">&quot;POST&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">label</span>&gt;</span>输入文本:<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;input_text&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;输入文本&quot;</span> /&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>发送<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"> &#123;% if response_text %&#125;</span><br><span class="line"> <span class="tag">&lt;<span class="name">p</span>&gt;</span>响应文本:&#123;&#123; response_text &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"> &#123;% endif %&#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure></p> <p>在这个 HTML 模板中,我们创建了一个表单,允许用户输入对话文本。当用户提交表单时,Web 应用程序会使用 ChatGPT 模型生成响应文本,并使用 Flask 的 <code>render_template</code> 函数将响应文本传递给 HTML 模板。</p> <p>要运行这个 Web 应用程序,你需要安装 Flask 和 Transformers 库,然后运行代码:</p> <p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pip install flask transformers</span><br><span class="line">python app.py</span><br></pre></td></tr></table></figure></p> <p>然后,你就可以在浏览器中访问<span class="exturl" data-url="aHR0cDovL2xvY2FsaG9zdDo1MDAwLw=="> http://localhost:5000/</span> 来使用这个 Web 应用程序了。</p> <p>要在上述代码的基础上创建一个更美观的界面,你可以使用 HTML、CSS 和 JavaScript 来设计界面,并使用 AJAX 技术在用户输入文本后异步获取 ChatGPT 响应。</p> <p>下面是一个示例代码,展示了如何使用这些技术创建一个类似聊天系统的界面:</p> <p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">title</span>&gt;</span>ChatGPT Demo<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 引入Bootstrap框架 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css&quot;</span> <span class="attr">integrity</span>=<span class="string">&quot;sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk&quot;</span> <span class="attr">crossorigin</span>=<span class="string">&quot;anonymous&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 创建聊天窗口 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;container mt-5&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;card&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;card-header&quot;</span>&gt;</span></span><br><span class="line"> 聊天窗口</span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;card-body p-0&quot;</span> <span class="attr">id</span>=<span class="string">&quot;messages&quot;</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 显示聊天记录 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;row mb-2&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;col-md-2&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;col-md-10 text-right&quot;</span>&gt;</span></span><br><span class="line"> 你好,我是ChatGPT,有什么想聊的?</span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 创建输入框 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;card-footer&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">form</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;form-group&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">class</span>=<span class="string">&quot;form-control&quot;</span> <span class="attr">id</span>=<span class="string">&quot;input_text&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;输入文本&quot;</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">class</span>=<span class="string">&quot;btn btn-primary&quot;</span> <span class="attr">id</span>=<span class="string">&quot;send_button&quot;</span>&gt;</span>发送<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- 引入jQuery库 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://code.jquery.com/jquery-3.5.1.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"> <span class="comment">&lt;!-- 设置AJAX请求 --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> $(<span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> $(<span class="string">&quot;form&quot;</span>).<span class="title function_">submit</span>(<span class="keyword">function</span>(<span class="params">event</span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> event.<span class="title function_">preventDefault</span>();</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 获取用户输入的文本</span></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">var</span> input_text = $(<span class="string">&quot;#input_text&quot;</span>).<span class="title function_">val</span>();</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 将文本添加到聊天记录中</span></span></span><br><span class="line"><span class="language-javascript"> $(<span class="string">&quot;#messages&quot;</span>).<span class="title function_">append</span>(</span></span><br><span class="line"><span class="language-javascript"> <span class="string">&#x27;&lt;div class=&quot;row mb-2&quot;&gt;&lt;div class=&quot;col-md-2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;col-md-10&quot;&gt;&#x27;</span> + input_text + <span class="string">&#x27;&lt;/div&gt;&lt;/div&gt;&#x27;</span></span></span><br><span class="line"><span class="language-javascript"> );</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 发送AJAX请求</span></span></span><br><span class="line"><span class="language-javascript"> $.<span class="title function_">ajax</span>(&#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">type</span>: <span class="string">&quot;POST&quot;</span>,</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">url</span>: <span class="string">&quot;/chat&quot;</span>,</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="string">&quot;input_text&quot;</span>: input_text</span></span><br><span class="line"><span class="language-javascript"> &#125;,</span></span><br><span class="line"><span class="language-javascript"> <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">response</span>) &#123;</span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 将GPT的回复添加到聊天记录中</span></span></span><br><span class="line"><span class="language-javascript"> $(<span class="string">&quot;#messages&quot;</span>).<span class="title function_">append</span>(</span></span><br><span class="line"><span class="language-javascript"> <span class="string">&#x27;&lt;div class=&quot;row mb-2&quot;&gt;&lt;div class=&quot;col-md-10 text-left&quot;&gt;&#x27;</span> + response + <span class="string">&#x27;&lt;/div&gt;&lt;div class=&quot;col-md-2&quot;&gt;&lt;/div&gt;&lt;/div&gt;&#x27;</span></span></span><br><span class="line"><span class="language-javascript"> );</span></span><br><span class="line"><span class="language-javascript"> &#125;</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"> &#125;);</span></span><br><span class="line"><span class="language-javascript"> </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br></pre></td></tr></table></figure></p> <p>上面的代码是一个基于 HTML 和 jQuery 的聊天系统模板,使用了 Bootstrap 框架进行布局。</p> <ul> <li> <p>HTML 部分:</p> <ul> <li>页面中包含一个聊天窗口,其中有一个卡片(card),卡片中包含聊天记录(card-body)和输入框(card-footer)。</li> <li>聊天记录中默认显示一条消息:“你好,我是 ChatGPT,有什么想聊的?”</li> <li>输入框中包含一个文本输入框(input)和一个发送按钮(button)。</li> </ul> </li> <li> <p>jQuery 部分:</p> <ul> <li>页面加载完成后,通过 jQuery 监听表单提交事件(submit)。当表单提交时,jQuery 会触发一个回调函数,这个回调函数中的代码会被执行。</li> <li>当用户在输入框中输入文本并点击发送按钮时,表单提交事件(submit)被触发。</li> <li>在表单提交事件的回调函数中,首先使用 <code>event.preventDefault()</code> 阻止默认的表单提交行为。</li> <li>然后使用 <code>$(&quot;#input_text&quot;).val()</code> 获取用户输入的文本。</li> <li>接着使用 <code>$(&quot;#messages&quot;).append()</code> 将文本添加到聊天记录中。</li> <li>最后,使用 jQuery 的 AJAX 功能发送一个 POST 请求到服务器,将用户输入的文本作为请求参数。</li> <li>当服务器返回响应时,将服务器返回的内容添加到聊天记录中。</li> <li>最后,清空文本输入框,准备下一次聊天。</li> </ul> </li> <li> <p>整个流程如下:</p> <ol> <li>用户在文本输入框中输入文本,点击发送按钮。</li> <li>jQuery 监听到表单提交事件,阻止默认的表单提交行为。</li> <li>获取用户输入的文本。</li> <li>将文本添加到聊天记录中。</li> <li>发送 AJAX 请求,将用户输入的文本作为请求参数。</li> <li>服务器返回响应,将响应的内容添加到聊天记录中。</li> <li>清空文本输入框,准备下一次聊天。</li> </ol> <p>这个 HTML 模板只是个简单的框架,具体的逻辑实现还需要你在服务器端进行开发。</p> <p>感谢您阅读这篇文章,希望能帮助到您。在这篇文章中,我们介绍了如何将 ChatGPT 部署到网站上,并使用 jQuery 和 Bootstrap 构建聊天系统的界面。如果您有任何疑问或建议,欢迎在评论区留言。最后,如果这篇文章对您有所帮助,希望能给个打赏鼓励一下作者。<br /> 如果你觉得我的博客不错的话,可以赞助我 (・̀ ω・́)✧:<a href="https://jdjwzx233.cn/support">https://jdjwzx233.cn/support</a>。</p> </li> </ul>

2022/12/24
阅读更多

远程桌面控制器-用c++实现

<p>写一个远程桌面控制器是一个非常复杂的任务,需要熟悉许多网络协议、图像处理技术以及用户界面设计等知识。这里给出的是一个基本的框架,你可以在此基础上进行扩展和完善。</p> <p>首先,我们需要用到一些库来帮助我们实现远程桌面控制器。在这里,我们假设你使用的是 Windows 系统,并使用了以下几个库:</p> <ul> <li>WinSock:用于实现网络通信。</li> <li>GDI+:用于处理图像。</li> <li>MFC:用于创建图形用户界面。</li> </ul> <p>下面是使用这些库编写远程桌面控制器的基本步骤:</p> <ol> <li>创建一个 MFC 应用程序。</li> <li>使用 WinSock 库创建一个网络连接。</li> <li>使用 GDI+ 库获取远程桌面的屏幕截图。</li> <li>将屏幕截图显示在 MFC 窗口中。</li> <li>为用户提供一组控制命令,例如鼠标移动、鼠标单击、键盘输入等。</li> <li>使用 WinSock 库将用户的控制命令发送到远程桌面。</li> </ol> <p>下面是使用这些库编写远程桌面控制器的示例代码:</p> <p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;winsock2.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;gdiplus.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;afxwin.h&gt;</span> <span class="comment">// 包含 MFC 的头文件</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> Gdiplus;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个 Socket 类,用于封装网络通信相关的操作</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Socket</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> WSADATA m_wsaData;</span><br><span class="line"> SOCKET m_sock;</span><br><span class="line"> sockaddr_in m_serverAddr;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">Socket</span>() : <span class="built_in">m_sock</span>(INVALID_SOCKET) &#123;&#125;</span><br><span class="line"> <span class="comment">// 初始化 WinSock 库</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Init</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">WSAStartup</span>(<span class="built_in">MAKEWORD</span>(<span class="number">2</span>, <span class="number">2</span>), &amp;m_wsaData) != <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建套接字</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Create</span><span class="params">(<span class="type">int</span> af, <span class="type">int</span> type, <span class="type">int</span> protocol)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_sock = <span class="built_in">socket</span>(af, type, protocol);</span><br><span class="line"> <span class="keyword">if</span> (m_sock == INVALID_SOCKET)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 连接到服务器</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Connect</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* ip, <span class="type">unsigned</span> <span class="type">short</span> port)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_serverAddr.sin_family = AF_INET;</span><br><span class="line"> m_serverAddr.sin_port = <span class="built_in">htons</span>(port);</span><br><span class="line"> m_serverAddr.sin_addr.S_un.S_addr = <span class="built_in">inet_addr</span>(ip);</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">connect</span>(m_sock, (sockaddr*)&amp;m_serverAddr, <span class="built_in">sizeof</span>(m_serverAddr)) == SOCKET_ERROR)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送数据</span></span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">Send</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* buf, <span class="type">int</span> len)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">send</span>(m_sock, buf, len, <span class="number">0</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 接收数据</span></span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">Receive</span><span class="params">(<span class="type">char</span>* buf, <span class="type">int</span> len)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">recv</span>(m_sock, buf, len, <span class="number">0</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 关闭套接字</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Close</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="built_in">closesocket</span>(m_sock);</span><br><span class="line"> m_sock = INVALID_SOCKET;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 清理 WinSock 库</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Cleanup</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="built_in">WSACleanup</span>();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个 RemoteDesktop 类,用于控制远程桌面</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RemoteDesktop</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> Socket m_socket; <span class="comment">// 用于网络通信的套接字</span></span><br><span class="line"> Image* m_image; <span class="comment">// 当前屏幕截图</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">RemoteDesktop</span>() : <span class="built_in">m_image</span>(<span class="literal">NULL</span>) &#123;&#125;</span><br><span class="line"> <span class="comment">// 连接到远续桌面服务器</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Connect</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* ip, <span class="type">unsigned</span> <span class="type">short</span> port)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Init</span>())</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Create</span>(AF_INET, SOCK_STREAM, IPPROTO_TCP))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Connect</span>(ip, port))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 断开与远程桌面服务器的连接</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Disconnect</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_socket.<span class="built_in">Close</span>();</span><br><span class="line"> m_socket.<span class="built_in">Cleanup</span>();</span><br><span class="line"> <span class="keyword">delete</span> m_image;</span><br><span class="line"> m_image = <span class="literal">NULL</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取远程桌面的屏幕截图</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">GetScreenshot</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 先发送获取屏幕截图的命令</span></span><br><span class="line"> <span class="type">const</span> <span class="type">char</span>* cmd = <span class="string">&quot;screenshot&quot;</span>;</span><br><span class="line"> m_socket.<span class="built_in">Send</span>(cmd, <span class="built_in">strlen</span>(cmd));</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 接收屏幕截图的大小</span></span><br><span class="line"> <span class="type">int</span> size;</span><br><span class="line"> m_socket.<span class="built_in">Receive</span>((<span class="type">char</span>*)&amp;size, <span class="built_in">sizeof</span>(size));</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 分配内存空间,准备接收屏幕截图的数据</span></span><br><span class="line"> <span class="type">char</span>* data = <span class="keyword">new</span> <span class="type">char</span>[size];</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 接收屏幕截图的数据</span></span><br><span class="line"> <span class="type">int</span> bytesReceived = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (bytesReceived &lt; size)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="type">int</span> count = m_socket.<span class="built_in">Receive</span>(data + bytesReceived, size - bytesReceived);</span><br><span class="line"> <span class="keyword">if</span> (count &lt;= <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">delete</span>[] data;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> bytesReceived += count;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将接收到的数据转换为 GDI+ 图像</span></span><br><span class="line"> <span class="keyword">delete</span> m_image;</span><br><span class="line"> m_image = <span class="keyword">new</span> <span class="built_in">Image</span>(data, size);</span><br><span class="line"> <span class="keyword">delete</span>[] data;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取当前屏幕截图</span></span><br><span class="line"> <span class="function">Image* <span class="title">GetImage</span><span class="params">()</span> <span class="type">const</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">return</span> m_image;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送鼠标移动命令</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">MoveMouse</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 封装命令格式,发送命令</span></span><br><span class="line"> <span class="type">const</span> <span class="type">char</span>* cmd = <span class="string">&quot;mouse move&quot;</span>;</span><br><span class="line"> m_socket.<span class="built_in">Send</span>(cmd, <span class="built_in">strlen</span>(cmd));</span><br><span class="line"> m_socket.<span class="built_in">Send</span>((<span class="type">char</span>*)&amp;x, <span class="built_in">sizeof</span>(x));</span><br><span class="line"> m_socket.<span class="built_in">Send</span>((<span class="type">char</span>*)&amp;y, <span class="built_in">sizeof</span>(y));</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送鼠标单击命令</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">ClickMouse</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 封装命令格式,发送命令</span></span><br><span class="line"> <span class="type">const</span> <span class="type">char</span>* cmd = <span class="string">&quot;mouse click&quot;</span>;</span><br><span class="line"> m_socket.<span class="built_in">Send</span>(cmd, <span class="built_in">strlen</span>(cmd));</span><br><span class="line"> m_socket.<span class="built_in">Send</span>((<span class="type">char</span>*)&amp;x, <span class="built_in">sizeof</span>(x));</span><br><span class="line"> m_socket.<span class="built_in">Send</span>((<span class="type">char</span>*)&amp;y, <span class="built_in">sizeof</span>(y));</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送键盘输入命令</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">InputKey</span><span class="params">(<span class="type">int</span> keyCode)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 封装命令格式,发送命令</span></span><br><span class="line"> <span class="type">const</span> <span class="type">char</span>* cmd = <span class="string">&quot;key input&quot;</span>;</span><br><span class="line"> m_socket.<span class="built_in">Send</span>(cmd, <span class="built_in">strlen</span>(cmd));</span><br><span class="line"> m_socket.<span class="built_in">Send</span>((<span class="type">char</span>*)&amp;keyCode, <span class="built_in">sizeof</span>(keyCode));</span><br><span class="line"> &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个 RemoteDesktopDialog 类,用于显示远程桌面的界面</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RemoteDesktopDialog</span> : <span class="keyword">public</span> CDialog</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> RemoteDesktop m_rd; <span class="comment">// 用于控制远程桌面的对象</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="comment">// 使用 MFC 对话框的基本操作</span></span><br><span class="line"> <span class="built_in">RemoteDesktopDialog</span>() : <span class="built_in">CDialog</span>(IDD_DIALOG1) &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">DoDataExchange</span><span class="params">(CDataExchange* pDX)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> CDialog::<span class="built_in">DoDataExchange</span>(pDX);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="comment">// 连接到远程桌面服务器</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Connect</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* ip, <span class="type">unsigned</span> <span class="type">short</span> port)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">return</span> m_rd.<span class="built_in">Connect</span>(ip, port);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 断开与远程桌面服务器的连接</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Disconnect</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_rd.<span class="built_in">Disconnect</span>();</span><br><span class="line"> &#125;</span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line"> <span class="comment">// 绘制远程桌面的界面</span></span><br><span class="line"> <span class="function">afx_msg <span class="type">void</span> <span class="title">OnPaint</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="function">CPaintDC <span class="title">dc</span><span class="params">(<span class="keyword">this</span>)</span></span>; <span class="comment">// 用于绘制的设备上下文</span></span><br><span class="line"> CRect rect;</span><br><span class="line"> <span class="built_in">GetClientRect</span>(&amp;rect); <span class="comment">// 获取对话框的客户区域</span></span><br><span class="line"> <span class="comment">// 获取屏幕截图,并绘制到界面上</span></span><br><span class="line"> Image* image = m_rd.<span class="built_in">GetImage</span>();</span><br><span class="line"> <span class="keyword">if</span> (image != <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="function">Graphics <span class="title">graphics</span><span class="params">(dc)</span></span>;</span><br><span class="line"> graphics.<span class="built_in">DrawImage</span>(image, rect);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 处理鼠标移动事件</span></span><br><span class="line"> <span class="function">afx_msg <span class="type">void</span> <span class="title">OnMouseMove</span><span class="params">(UINT nFlags, CPoint point)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_rd.<span class="built_in">MoveMouse</span>(point.x, point.y);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 处理鼠标单击事件</span></span><br><span class="line"> <span class="function">afx_msg <span class="type">void</span> <span class="title">OnLButtonDown</span><span class="params">(UINT nFlags, CPoint point)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_rd.<span class="built_in">ClickMouse</span>(point.x, point.y);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 处理键盘输入事件</span></span><br><span class="line"> <span class="function">afx_msg <span class="type">void</span> <span class="title">OnKeyDown</span><span class="params">(UINT nChar, UINT nRepCnt, UINT nFlags)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_rd.<span class="built_in">InputKey</span>(nChar);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="built_in">DECLARE_MESSAGE_MAP</span>()</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">BEGIN_MESSAGE_MAP</span>(RemoteDesktopDialog, CDialog)</span><br><span class="line"> <span class="built_in">ON_WM_PAINT</span>()</span><br><span class="line"> <span class="built_in">ON_WM_MOUSEMOVE</span>()</span><br><span class="line"> <span class="built_in">ON_WM_LBUTTONDOWN</span>()</span><br><span class="line"> <span class="built_in">ON_WM_KEYDOWN</span>()</span><br><span class="line"><span class="built_in">END_MESSAGE_MAP</span>()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"> <span class="comment">// 初始化 GDI+</span></span><br><span class="line"> GdiplusStartupInput gdiplusStartupInput;</span><br><span class="line"> ULONG_PTR gdiplusToken;</span><br><span class="line"> <span class="built_in">GdiplusStartup</span>(&amp;gdiplusToken, &amp;gdiplusStartupInput, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="comment">// 创建对话框并运行</span></span><br><span class="line"> RemoteDesktopDialog dlg;</span><br><span class="line"> dlg.<span class="built_in">DoModal</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 清理 GDI+</span></span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></p> <p>在这段代码中,我们定义了三个类:Socket、RemoteDesktop 和 RemoteDesktopDialog。Socket 类封装了网络通信的相关操作,RemoteDesktop 类用于控制远程桌面,RemoteDesktopDialog 类用于显示远程桌面的界面。</p> <p>使用这个远程桌面控制器的流程如下:</p> <ol> <li>调用 Socket 类的 Init 函数初始化 WinSock 库。</li> <li>调用 Socket 类的 Create 函数创建一个套接字。</li> <li>调用 Socket 类的 Connect 函数连接到远程桌面服务器。</li> <li>调用 RemoteDesktop 类的 GetScreenshot 函数获取远程桌面的屏幕截图。</li> <li>调用 RemoteDesktop 类的 MoveMouse、ClickMouse 或 InputKey 函数发送控制命令。</li> <li>重复步骤 4 和 5,实时更新远程桌面的屏幕截图并发送控制命令。</li> <li>当远程桌面控制结束时,调用 RemoteDesktop 类的 Disconnect 函数断开与远程桌面服务器的连接,并调用 Socket 类的 Cleanup 函数清理 WinSock 库。</li> </ol> <p>需要注意的是,这段代码使用了 MFC 库来绘制界面,因此需要在 Visual Studio 中创建一个 MFC 应用程序,并在对话框资源中添加一个对话框。然后将上面的代码放入主窗口类的 .cpp 文件中,并在 .h 文件中声明相应的消息映射函数。</p> <p>以下是服务端代码:</p> <p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;GdiPlus.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;winsock2.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> comment(lib, <span class="string">&quot;gdiplus.lib&quot;</span>)</span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> comment(lib, <span class="string">&quot;ws2_32.lib&quot;</span>)</span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> Gdiplus;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个 Socket 类,用于封装网络通信相关的操作</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Socket</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> WSADATA m_wsaData;</span><br><span class="line"> SOCKET m_sock;</span><br><span class="line"> sockaddr_in m_serverAddr;</span><br><span class="line"> sockaddr_in m_clientAddr;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">Socket</span>() : <span class="built_in">m_sock</span>(INVALID_SOCKET) &#123;&#125;</span><br><span class="line"> <span class="comment">// 初始化 WinSock 库</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Init</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">WSAStartup</span>(<span class="built_in">MAKEWORD</span>(<span class="number">2</span>, <span class="number">2</span>), &amp;m_wsaData) != <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建套接字</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Create</span><span class="params">(<span class="type">int</span> af, <span class="type">int</span> type, <span class="type">int</span> protocol)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> m_sock = <span class="built_in">socket</span>(af, type, protocol);</span><br><span class="line"> <span class="keyword">if</span> (m_sock == INVALID_SOCKET)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 绑定套接字到本地地址和端口</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Bind</span><span class="params">(<span class="type">unsigned</span> <span class="type">short</span> port)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="built_in">memset</span>(&amp;m_serverAddr, <span class="number">0</span>, <span class="built_in">sizeof</span>(m_serverAddr));</span><br><span class="line"> m_serverAddr.sin_family = AF_INET;</span><br><span class="line"> m_serverAddr.sin_addr.s_addr = <span class="built_in">htonl</span>(INADDR_ANY);</span><br><span class="line"> m_serverAddr.sin_port = <span class="built_in">htons</span>(port);</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">bind</span>(m_sock, (sockaddr*)&amp;m_serverAddr, <span class="built_in">sizeof</span>(m_serverAddr)) == SOCKET_ERROR)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 监听套接字</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Listen</span><span class="params">(<span class="type">int</span> backlog)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">listen</span>(m_sock, backlog) == SOCKET_ERROR)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 接受客户端的连接</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Accept</span><span class="params">(Socket&amp; client)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="type">int</span> addrLen = <span class="built_in">sizeof</span>(m_clientAddr);</span><br><span class="line"> client.m_sock = <span class="built_in">accept</span>(m_sock, (sockaddr*)&amp;m_clientAddr, &amp;addrLen);</span><br><span class="line"> <span class="keyword">if</span> (client.m_sock == INVALID_SOCKET)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 接收数据</span></span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">Receive</span><span class="params">(<span class="type">char</span>* buffer, <span class="type">int</span> len)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">recv</span>(m_sock, buffer, len, <span class="number">0</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送数据</span></span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">Send</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* buffer, <span class="type">int</span> len)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">send</span>(m_sock, buffer, len, <span class="number">0</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 关闭套接字</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Close</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="built_in">closesocket</span>(m_sock);</span><br><span class="line"> m_sock = INVALID_SOCKET;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 清理 WinSock 库</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Cleanup</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="built_in">WSACleanup</span>();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个 RemoteDesktopServer 类,用于提供远程桌面服务</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RemoteDesktopServer</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> Socket m_socket; <span class="comment">// 用于网络通信的套接字</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="comment">// 初始化远程桌面服务器</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">Init</span><span class="params">(<span class="type">unsigned</span> <span class="type">short</span> port)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Init</span>())</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Create</span>(AF_INET, SOCK_STREAM, IPPROTO_TCP))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Bind</span>(port))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Listen</span>(<span class="number">10</span>))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 运行远程桌面服务器</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">Run</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 不断循环,接受客户端的连接</span></span><br><span class="line"> <span class="keyword">while</span> (<span class="literal">true</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> Socket client;</span><br><span class="line"> <span class="keyword">if</span> (!m_socket.<span class="built_in">Accept</span>(client))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 为客户端创建一个线程,用于处理客户端的请求</span></span><br><span class="line"> HANDLE hThread = <span class="built_in">CreateThread</span>(<span class="literal">NULL</span>, <span class="number">0</span>, ClientThreadProc, &amp;client, <span class="number">0</span>, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (hThread == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> client.<span class="built_in">Close</span>();</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="built_in">CloseHandle</span>(hThread);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="comment">// 客户端线程的回调函数,用于处理客户端的请求</span></span><br><span class="line"> <span class="function"><span class="type">static</span> DWORD WINAPI <span class="title">ClientThreadProc</span><span class="params">(LPVOID lpParam)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> Socket* pClient = (Socket*)lpParam;</span><br><span class="line"> <span class="comment">// 不断循环,处理客户端的请求</span></span><br><span class="line"> <span class="keyword">while</span> (<span class="literal">true</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="comment">// 接收客户端的命令</span></span><br><span class="line"> <span class="type">char</span> cmd[<span class="number">256</span>];</span><br><span class="line"> <span class="type">int</span> len = pClient-&gt;<span class="built_in">Receive</span>(cmd, <span class="built_in">sizeof</span>(cmd));</span><br><span class="line"> <span class="keyword">if</span> (len &lt;= <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 根据命令类型执行相应的操作</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">strcmp</span>(cmd, <span class="string">&quot;screenshot&quot;</span>) == <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="comment">// 处理屏幕截图请求</span></span><br><span class="line"> <span class="built_in">HandleScreenshotRequest</span>(*pClient);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">strcmp</span>(cmd, <span class="string">&quot;mouse move&quot;</span>) == <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="comment">// 处理鼠标移动请求</span></span><br><span class="line"> <span class="type">int</span> x, y;</span><br><span class="line"> pClient-&gt;<span class="built_in">Receive</span>((<span class="type">char</span>*)&amp;x, <span class="built_in">sizeof</span>(x));</span><br><span class="line"> pClient-&gt;<span class="built_in">Receive</span>((<span class="type">char</span>*)&amp;y, <span class="built_in">sizeof</span>(y));</span><br><span class="line"> <span class="built_in">HandleMouseMoveRequest</span>(x, y);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">strcmp</span>(cmd, <span class="string">&quot;mouse click&quot;</span>) == <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="comment">// 处理鼠标单击请求</span></span><br><span class="line"> <span class="type">int</span> x, y;</span><br><span class="line"> pClient-&gt;<span class="built_in">Receive</span>((<span class="type">char</span>*)&amp;x, <span class="built_in">sizeof</span>(x));</span><br><span class="line"> pClient-&gt;<span class="built_in">Receive</span>((<span class="type">char</span>*)&amp;y, <span class="built_in">sizeof</span>(y));</span><br><span class="line"> <span class="built_in">HandleMouseClickRequest</span>(x, y);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">strcmp</span>(cmd, <span class="string">&quot;key input&quot;</span>) == <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="comment">// 处理键盘输入请求</span></span><br><span class="line"> <span class="type">char</span> key;</span><br><span class="line"> pClient-&gt;<span class="built_in">Receive</span>(&amp;key, <span class="built_in">sizeof</span>(key));</span><br><span class="line"> <span class="built_in">HandleKeyInputRequest</span>(key);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 关闭客户端的套接字</span></span><br><span class="line"> pClient-&gt;<span class="built_in">Close</span>();</span><br><span class="line"> <span class="keyword">delete</span> pClient;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 处理屏幕截图请求</span></span><br><span class="line"> <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">HandleScreenshotRequest</span><span class="params">(Socket&amp; client)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 获取屏幕的宽高</span></span><br><span class="line"> <span class="type">int</span> width = <span class="built_in">GetSystemMetrics</span>(SM_CXSCREEN);</span><br><span class="line"> <span class="type">int</span> height = <span class="built_in">GetSystemMetrics</span>(SM_CYSCREEN);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建内存 DC</span></span><br><span class="line"> HDC hdcMem = <span class="built_in">CreateCompatibleDC</span>(<span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (hdcMem == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建位图</span></span><br><span class="line"> HBITMAP hbm = <span class="built_in">CreateCompatibleBitmap</span>(<span class="built_in">GetDC</span>(<span class="literal">NULL</span>), width, height);</span><br><span class="line"> <span class="keyword">if</span> (hbm == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将位图选入内存 DC</span></span><br><span class="line"> HBITMAP hbmOld = (HBITMAP)<span class="built_in">SelectObject</span>(hdcMem, hbm);</span><br><span class="line"> <span class="keyword">if</span> (hbmOld == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbm);</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将屏幕拷贝到内存 DC</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">BitBlt</span>(hdcMem, <span class="number">0</span>, <span class="number">0</span>, width, height, <span class="built_in">GetDC</span>(<span class="literal">NULL</span>), <span class="number">0</span>, <span class="number">0</span>, SRCCOPY))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">SelectObject</span>(hdcMem, hbmOld);</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbm);</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将内存 DC 的图像保存到缓冲区</span></span><br><span class="line"> BITMAPINFOHEADER bih;</span><br><span class="line"> <span class="built_in">memset</span>(&amp;bih, <span class="number">0</span>, <span class="built_in">sizeof</span>(bih));</span><br><span class="line"> bih.biSize = <span class="built_in">sizeof</span>(bih);</span><br><span class="line"> bih.biWidth = width;</span><br><span class="line"> bih.biHeight = -height;</span><br><span class="line"> bih.biPlanes = <span class="number">1</span>;</span><br><span class="line"> bih.biBitCount = <span class="number">24</span>;</span><br><span class="line"> bih.biCompression = BI_RGB;</span><br><span class="line"> BYTE* pBuf = <span class="literal">NULL</span>;</span><br><span class="line"> HBITMAP hbmDib = <span class="built_in">CreateDIBSection</span>(hdcMem, (BITMAPINFO*)&amp;bih, DIB_RGB_COLORS, (<span class="type">void</span>**)&amp;pBuf, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> (hbmDib == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">SelectObject</span>(hdcMem, hbmOld);</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbm);</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 将内存 DC 的图像复制到位图中</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">SelectObject</span>(hdcMem, hbmDib))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbmDib);</span><br><span class="line"> <span class="built_in">SelectObject</span>(hdcMem, hbmOld);</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbm);</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 将位图的图像转换为 JPEG 格式并发送到客户端</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">SendScreenshot</span>(client, pBuf, width, height))</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbmDib);</span><br><span class="line"> <span class="built_in">SelectObject</span>(hdcMem, hbmOld);</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbm);</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 清理资源</span></span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbmDib);</span><br><span class="line"> <span class="built_in">SelectObject</span>(hdcMem, hbmOld);</span><br><span class="line"> <span class="built_in">DeleteObject</span>(hbm);</span><br><span class="line"> <span class="built_in">DeleteDC</span>(hdcMem);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将位图的图像转换为 JPEG 格式并发送到客户端</span></span><br><span class="line"> <span class="function"><span class="type">static</span> <span class="type">bool</span> <span class="title">SendScreenshot</span><span class="params">(Socket&amp; client, BYTE* pBuf, <span class="type">int</span> width, <span class="type">int</span> height)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 初始化 GDI+</span></span><br><span class="line"> GdiplusStartupInput gdiplusStartupInput;</span><br><span class="line"> ULONG_PTR gdiplusToken;</span><br><span class="line"> <span class="built_in">GdiplusStartup</span>(&amp;gdiplusToken, &amp;gdiplusStartupInput, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将位图的图像转换为 JPEG 格式</span></span><br><span class="line"> <span class="function">Bitmap <span class="title">bmp</span><span class="params">(width, height, width * <span class="number">3</span>, PixelFormat24bppRGB, pBuf)</span></span>;</span><br><span class="line"> CLSID clsid;</span><br><span class="line"> <span class="built_in">GetEncoderClsid</span>(<span class="string">L&quot;image/jpeg&quot;</span>, &amp;clsid);</span><br><span class="line"> IStream* pStream = <span class="literal">NULL</span>;</span><br><span class="line"> bmp.<span class="built_in">Save</span>(<span class="string">L&quot;screenshot.jpg&quot;</span>, &amp;clsid, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">CreateStreamOnHGlobal</span>(<span class="literal">NULL</span>, TRUE, &amp;pStream) != S_OK)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> bmp.<span class="built_in">Save</span>(pStream, &amp;clsid, <span class="literal">NULL</span>);</span><br><span class="line"> HGLOBAL hGlobal = <span class="literal">NULL</span>; <span class="comment">// 修改为 HGLOBAL 类型</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">GetHGlobalFromStream</span>(pStream, &amp;hGlobal) != S_OK) <span class="comment">// 修改为 HGLOBAL 类型</span></span><br><span class="line"> &#123;</span><br><span class="line"> pStream-&gt;<span class="built_in">Release</span>();</span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> ULONG cbSize = <span class="built_in">GlobalSize</span>(hGlobal); <span class="comment">// 修改为 HGLOBAL 类型</span></span><br><span class="line"> BYTE* pJpegBuf = (BYTE*)<span class="built_in">GlobalLock</span>(hGlobal); <span class="comment">// 修改为 HGLOBAL 类型</span></span><br><span class="line"> <span class="keyword">if</span> (pJpegBuf == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> pStream-&gt;<span class="built_in">Release</span>();</span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> LARGE_INTEGER li;</span><br><span class="line"> li.QuadPart = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (pStream-&gt;<span class="built_in">Seek</span>(li, STREAM_SEEK_SET, <span class="literal">NULL</span>) != S_OK)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">GlobalFree</span>(pJpegBuf);</span><br><span class="line"> pStream-&gt;<span class="built_in">Release</span>();</span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (pStream-&gt;<span class="built_in">Read</span>(pJpegBuf, cbSize, <span class="literal">NULL</span>) != S_OK)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">GlobalFree</span>(pJpegBuf);</span><br><span class="line"> pStream-&gt;<span class="built_in">Release</span>();</span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> pStream-&gt;<span class="built_in">Release</span>();</span><br><span class="line"> <span class="built_in">GdiplusShutdown</span>(gdiplusToken);</span><br><span class="line"> <span class="comment">// 将 JPEG 数据的长度发送到客户端</span></span><br><span class="line"> <span class="keyword">if</span> (client.<span class="built_in">Send</span>((<span class="type">char</span>*)&amp;cbSize, <span class="built_in">sizeof</span>(cbSize)) &lt;= <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">GlobalFree</span>(pJpegBuf);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将 JPEG 数据发送到客户端</span></span><br><span class="line"> <span class="keyword">if</span> (client.<span class="built_in">Send</span>((<span class="type">char</span>*)pJpegBuf, cbSize) &lt;= <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="built_in">GlobalFree</span>(pJpegBuf);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 清理资源</span></span><br><span class="line"> <span class="built_in">GlobalFree</span>(pJpegBuf);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取图像编码器的 CLSID</span></span><br><span class="line"> <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">GetEncoderClsid</span><span class="params">(<span class="type">const</span> WCHAR* format, CLSID* pClsid)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> UINT num = <span class="number">0</span>, size = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">GetImageEncodersSize</span>(&amp;num, &amp;size);</span><br><span class="line"> <span class="keyword">if</span> (size == <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)<span class="built_in">malloc</span>(size);</span><br><span class="line"> <span class="keyword">if</span> (pImageCodecInfo == <span class="literal">NULL</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="built_in">GetImageEncoders</span>(num, size, pImageCodecInfo);</span><br><span class="line"> <span class="keyword">for</span> (UINT i = <span class="number">0</span>; i &lt; num; ++i)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">wcscmp</span>(pImageCodecInfo[i].MimeType, format) == <span class="number">0</span>)</span><br><span class="line"> &#123;</span><br><span class="line"> *pClsid = pImageCodecInfo[i].Clsid;</span><br><span class="line"> <span class="built_in">free</span>(pImageCodecInfo);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="built_in">free</span>(pImageCodecInfo);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 处理鼠标移动请求</span></span><br><span class="line"> <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">HandleMouseMoveRequest</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 获取屏幕的宽高</span></span><br><span class="line"> <span class="type">int</span> width = <span class="built_in">GetSystemMetrics</span>(SM_CXSCREEN);</span><br><span class="line"> <span class="type">int</span> height = <span class="built_in">GetSystemMetrics</span>(SM_CYSCREEN);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 计算相对于屏幕的坐标</span></span><br><span class="line"> <span class="type">double</span> fx = (<span class="type">double</span>)x / <span class="number">65535.0</span>;</span><br><span class="line"> <span class="comment">// 移动鼠标</span></span><br><span class="line"> <span class="built_in">SetCursorPos</span>(x, y);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 处理鼠标单击请求</span></span><br><span class="line"> <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">HandleMouseClickRequest</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 获取屏幕的宽高</span></span><br><span class="line"> <span class="type">int</span> width = <span class="built_in">GetSystemMetrics</span>(SM_CXSCREEN);</span><br><span class="line"> <span class="type">int</span> height = <span class="built_in">GetSystemMetrics</span>(SM_CYSCREEN);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 计算相对于屏幕的坐标</span></span><br><span class="line"> <span class="type">double</span> fx = (<span class="type">double</span>)x / <span class="number">65535.0</span>;</span><br><span class="line"> <span class="type">double</span> fy = (<span class="type">double</span>)y / <span class="number">65535.0</span>;</span><br><span class="line"> <span class="type">int</span> cx = (<span class="type">int</span>)(fx * width);</span><br><span class="line"> <span class="type">int</span> cy = (<span class="type">int</span>)(fy * height);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 移动鼠标</span></span><br><span class="line"> <span class="built_in">SetCursorPos</span>(cx, cy);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送鼠标左键单击消息</span></span><br><span class="line"> INPUT input;</span><br><span class="line"> <span class="built_in">memset</span>(&amp;input, <span class="number">0</span>, <span class="built_in">sizeof</span>(input));</span><br><span class="line"> input.type = INPUT_MOUSE;</span><br><span class="line"> input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;</span><br><span class="line"> <span class="built_in">SendInput</span>(<span class="number">1</span>, &amp;input, <span class="built_in">sizeof</span>(input));</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 处理键盘输入请求</span></span><br><span class="line"> <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">HandleKeyInputRequest</span><span class="params">(<span class="type">char</span> key)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line"> <span class="comment">// 获取键盘的输入模式</span></span><br><span class="line"> HKL layout = <span class="built_in">GetKeyboardLayout</span>(<span class="number">0</span>);</span><br><span class="line"> UINT vk = <span class="built_in">MapVirtualKeyExA</span>(<span class="built_in">VkKeyScanExA</span>(key, layout), <span class="number">0</span>, layout);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送键盘输入消息</span></span><br><span class="line"> INPUT input;</span><br><span class="line"> <span class="built_in">memset</span>(&amp;input, <span class="number">0</span>, <span class="built_in">sizeof</span>(input));</span><br><span class="line"> input.type = INPUT_KEYBOARD;</span><br><span class="line"> input.ki.wVk = vk;</span><br><span class="line"> <span class="built_in">SendInput</span>(<span class="number">1</span>, &amp;input, <span class="built_in">sizeof</span>(input));</span><br><span class="line"> &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> Socket m_socket; <span class="comment">// 监听套接字</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"> RemoteDesktopServer server;</span><br><span class="line"> <span class="keyword">if</span> (!server.<span class="built_in">Init</span>(<span class="number">5555</span>))</span><br><span class="line"> &#123;</span><br><span class="line"> cout&lt;&lt;<span class="string">&quot;启动服务器失败!&quot;</span>&lt;&lt;endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> server.<span class="built_in">Run</span>();</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></p> <p>希望这些代码能帮到你!</p>

2022/12/23
阅读更多

推荐订阅

每日新闻.

The Art of Chawye Hsu

Recent content on Yuko's Blog