<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>H5开发工具 - 网页打包, 全景VR,  AI助手,  APK加固混淆, JS加密混淆保护技术分享</title><link>https://www.h5pack.com/</link><description></description><item><title>HTML打包APK实现视频全屏播放教程</title><link>https://www.h5pack.com/post/html-apk-video-fullscreen-player.html</link><description>&lt;p&gt;HTML页面可以通过 &lt;code&gt;video&lt;/code&gt; 标签播放网络和本地视频，结合浏览器全屏接口实现最大化播放，并在全屏时锁定横屏获得更好的观看体验。完成页面代码后，再通过HTML一键打包APK工具配置网络权限，即可生成支持视频播放和全屏播放的安卓APP。&lt;/p&gt;&lt;p&gt;如果你不了解HTML打包APK工具，可以访问官网查看详情：&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://html2apk.leapever.com/&quot;&gt;HTML一键打包APK工具官网&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;创建视频播放页面&lt;/h2&gt;&lt;p&gt;在HTML项目入口目录中创建 &lt;code&gt;index.html&lt;/code&gt;，页面包含视频播放区、最大化按钮和地址加载入口。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;视频播放：使用 &lt;code&gt;video&lt;/code&gt; 标签加载网络或本地视频，并添加 &lt;code&gt;playsinline&lt;/code&gt; 系列属性保证在APP内联播放。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;最大化按钮：调用浏览器全屏接口，将播放器切换到全屏状态，兼容打包后APP的WebView环境。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;横屏锁定：进入全屏时自动锁定为横屏，退出全屏时恢复竖屏。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;地址加载：支持输入视频直链地址，加载不同的视频进行测试。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;视频标签需要添加 &lt;code&gt;playsinline&lt;/code&gt;、&lt;code&gt;webkit-playsinline&lt;/code&gt; 和 &lt;code&gt;x5-playsinline&lt;/code&gt; 属性，避免在部分WebView中点击播放时强制跳转系统播放器：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-html&quot;&gt;&amp;lt;video&amp;nbsp;playsinline&amp;nbsp;webkit-playsinline&amp;nbsp;x5-playsinline&amp;nbsp;src=&amp;quot;video.mp4&amp;quot;&amp;gt;&amp;lt;/video&amp;gt;&lt;/pre&gt;&lt;p&gt;最大化按钮通过全屏接口把播放器容器切换到全屏，并同时处理标准接口和 &lt;code&gt;webkit&lt;/code&gt; 前缀接口，保证在打包后的WebView中正常工作：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-javascript&quot;&gt;if&amp;nbsp;(shell.requestFullscreen)&amp;nbsp;shell.requestFullscreen();
else&amp;nbsp;if&amp;nbsp;(shell.webkitRequestFullscreen)&amp;nbsp;shell.webkitRequestFullscreen();&lt;/pre&gt;&lt;h2&gt;打包成APK&lt;/h2&gt;&lt;p&gt;复制上述HTML代码, 保存到video-test.html文件中, 然后HTML一键打包APK工具中载入该文件, 然后点击打包生成APP即可&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1786361555393_1c825fa7.png&quot; alt=&quot;把html打包成apk&quot;/&gt;&lt;/p&gt;&lt;h2&gt;安装并测试功能&lt;/h2&gt;&lt;p&gt;将生成的APK安装到安卓手机，依次测试页面中的各项功能：&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;打开APP，确认默认视频可以正常加载，点击“播放 / 暂停”按钮可以控制播放。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;点击右上角的最大化按钮，确认播放器进入全屏状态，按钮图标切换为还原样式。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在全屏状态下旋转手机，确认画面锁定为横屏；退出全屏后确认恢复竖屏显示。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在地址栏中输入其他mp4直链地址并点击“加载”，确认可以切换播放不同的视频。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;拖动进度条，确认视频可以从指定位置继续播放。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;为了获得最好的兼容性，视频建议使用H.264视频编码和AAC音频编码的mp4文件。部分WebView版本对HEVC、VP9等编码的支持不一致，可能出现只有声音没有画面的情况。&lt;/p&gt;&lt;p&gt;如果点击最大化按钮没有进入全屏，请先确认APP系统设置中没有限制横屏，并检查手机是否开启了方向锁定；如果在线视频一直无法加载，请检查打包时是否勾选了网络权限，以及视频地址是否可以通过手机浏览器直接打开。网页中的自动播放在WebView里通常需要先有一次用户交互，因此建议像示例一样提供明确的播放按钮，而不是依赖页面打开后自动播放。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1786361555657_c0490173.png&quot; alt=&quot;视频播放和最大化页面&quot;/&gt;&lt;/p&gt;&lt;p&gt;一个完整的html示例代码如下：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-html&quot;&gt;&amp;lt;!DOCTYPE&amp;nbsp;html&amp;gt;
&amp;lt;html&amp;nbsp;lang=&amp;quot;zh-CN&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta&amp;nbsp;charset=&amp;quot;UTF-8&amp;quot;&amp;gt;
&amp;lt;meta&amp;nbsp;name=&amp;quot;viewport&amp;quot;&amp;nbsp;content=&amp;quot;width=device-width,&amp;nbsp;initial-scale=1.0,&amp;nbsp;maximum-scale=1.0,&amp;nbsp;user-scalable=no&amp;quot;&amp;gt;
&amp;lt;title&amp;gt;视频播放测试&amp;lt;/title&amp;gt;
&amp;lt;style&amp;gt;
&amp;nbsp;&amp;nbsp;*&amp;nbsp;{&amp;nbsp;margin:&amp;nbsp;0;&amp;nbsp;padding:&amp;nbsp;0;&amp;nbsp;box-sizing:&amp;nbsp;border-box;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;html,&amp;nbsp;body&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;&amp;nbsp;height:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#000;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-family:&amp;nbsp;-apple-system,&amp;nbsp;&amp;quot;PingFang&amp;nbsp;SC&amp;quot;,&amp;nbsp;&amp;quot;Microsoft&amp;nbsp;YaHei&amp;quot;,&amp;nbsp;sans-serif;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;#player-wrap&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;relative;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex-direction:&amp;nbsp;column;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;/*&amp;nbsp;视频区域&amp;nbsp;*/
&amp;nbsp;&amp;nbsp;#video-box&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;relative;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex:&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#000;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;align-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;justify-content:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;video&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;object-fit:&amp;nbsp;contain;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#000;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;/*&amp;nbsp;最大化按钮（悬浮在视频右上角）&amp;nbsp;*/
&amp;nbsp;&amp;nbsp;#btn-fullscreen&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;absolute;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;top:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;right:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;z-index:&amp;nbsp;20;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;44px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;44px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;none;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;rgba(0,&amp;nbsp;0,&amp;nbsp;0,&amp;nbsp;0.55);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;align-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;justify-content:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;pointer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-webkit-tap-highlight-color:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;#btn-fullscreen:active&amp;nbsp;{&amp;nbsp;background:&amp;nbsp;rgba(255,&amp;nbsp;255,&amp;nbsp;255,&amp;nbsp;0.25);&amp;nbsp;}
&amp;nbsp;&amp;nbsp;#btn-fullscreen&amp;nbsp;svg&amp;nbsp;{&amp;nbsp;width:&amp;nbsp;24px;&amp;nbsp;height:&amp;nbsp;24px;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;/*&amp;nbsp;底部控制栏&amp;nbsp;*/
&amp;nbsp;&amp;nbsp;#controls&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;relative;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;z-index:&amp;nbsp;10;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#111;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;10px&amp;nbsp;12px&amp;nbsp;calc(10px&amp;nbsp;+&amp;nbsp;env(safe-area-inset-bottom));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex-direction:&amp;nbsp;column;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gap:&amp;nbsp;10px;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;#btn-play&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;17px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#1f80ff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;none;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;10px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-webkit-tap-highlight-color:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;#btn-play:active&amp;nbsp;{&amp;nbsp;opacity:&amp;nbsp;0.8;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;.url-row&amp;nbsp;{&amp;nbsp;display:&amp;nbsp;flex;&amp;nbsp;gap:&amp;nbsp;8px;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;#url-input&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex:&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-width:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#222;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;#333;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outline:&amp;nbsp;none;
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;#btn-load&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;0&amp;nbsp;16px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#333;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;none;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space:&amp;nbsp;nowrap;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;#status&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#888;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;word-break:&amp;nbsp;break-all;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;/*&amp;nbsp;全屏时隐藏控制栏&amp;nbsp;*/
&amp;nbsp;&amp;nbsp;:fullscreen&amp;nbsp;#controls&amp;nbsp;{&amp;nbsp;display:&amp;nbsp;none;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;:-webkit-full-screen&amp;nbsp;#controls&amp;nbsp;{&amp;nbsp;display:&amp;nbsp;none;&amp;nbsp;}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;div&amp;nbsp;id=&amp;quot;player-wrap&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;id=&amp;quot;video-box&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;video&amp;nbsp;id=&amp;quot;video&amp;quot;&amp;nbsp;playsinline&amp;nbsp;webkit-playsinline&amp;nbsp;x5-playsinline&amp;nbsp;preload=&amp;quot;metadata&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;src=&amp;quot;./BigBuckBunny.mp4&amp;quot;&amp;gt;&amp;lt;/video&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;!--&amp;nbsp;最大化按钮&amp;nbsp;--&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;btn-fullscreen&amp;quot;&amp;nbsp;aria-label=&amp;quot;最大化&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;svg&amp;nbsp;id=&amp;quot;icon-max&amp;quot;&amp;nbsp;viewBox=&amp;quot;0&amp;nbsp;0&amp;nbsp;24&amp;nbsp;24&amp;quot;&amp;nbsp;fill=&amp;quot;none&amp;quot;&amp;nbsp;stroke=&amp;quot;currentColor&amp;quot;&amp;nbsp;stroke-width=&amp;quot;2&amp;quot;&amp;nbsp;stroke-linecap=&amp;quot;round&amp;quot;&amp;nbsp;stroke-linejoin=&amp;quot;round&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;path&amp;nbsp;d=&amp;quot;M8&amp;nbsp;3H5a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;0-2&amp;nbsp;2v3&amp;quot;/&amp;gt;&amp;lt;path&amp;nbsp;d=&amp;quot;M16&amp;nbsp;3h3a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;1&amp;nbsp;2&amp;nbsp;2v3&amp;quot;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;path&amp;nbsp;d=&amp;quot;M8&amp;nbsp;21H5a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;1-2-2v-3&amp;quot;/&amp;gt;&amp;lt;path&amp;nbsp;d=&amp;quot;M16&amp;nbsp;21h3a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;0&amp;nbsp;2-2v-3&amp;quot;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/svg&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;svg&amp;nbsp;id=&amp;quot;icon-min&amp;quot;&amp;nbsp;viewBox=&amp;quot;0&amp;nbsp;0&amp;nbsp;24&amp;nbsp;24&amp;quot;&amp;nbsp;fill=&amp;quot;none&amp;quot;&amp;nbsp;stroke=&amp;quot;currentColor&amp;quot;&amp;nbsp;stroke-width=&amp;quot;2&amp;quot;&amp;nbsp;stroke-linecap=&amp;quot;round&amp;quot;&amp;nbsp;stroke-linejoin=&amp;quot;round&amp;quot;&amp;nbsp;style=&amp;quot;display:none&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;path&amp;nbsp;d=&amp;quot;M8&amp;nbsp;3v3a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;1-2&amp;nbsp;2H3&amp;quot;/&amp;gt;&amp;lt;path&amp;nbsp;d=&amp;quot;M21&amp;nbsp;8h-3a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;1-2-2V3&amp;quot;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;path&amp;nbsp;d=&amp;quot;M3&amp;nbsp;16h3a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;1&amp;nbsp;2&amp;nbsp;2v3&amp;quot;/&amp;gt;&amp;lt;path&amp;nbsp;d=&amp;quot;M16&amp;nbsp;21v-3a2&amp;nbsp;2&amp;nbsp;0&amp;nbsp;0&amp;nbsp;1&amp;nbsp;2-2h3&amp;quot;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/svg&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;id=&amp;quot;controls&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;btn-play&amp;quot;&amp;gt;播放&amp;nbsp;/&amp;nbsp;暂停&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;url-row&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input&amp;nbsp;id=&amp;quot;url-input&amp;quot;&amp;nbsp;type=&amp;quot;url&amp;quot;&amp;nbsp;placeholder=&amp;quot;输入视频地址&amp;nbsp;(mp4/m3u8直链)&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;btn-load&amp;quot;&amp;gt;加载&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;id=&amp;quot;status&amp;quot;&amp;gt;就绪&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;script&amp;gt;
(function&amp;nbsp;()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;var&amp;nbsp;wrap&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;player-wrap&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;video&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;video&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;btnFs&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;btn-fullscreen&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;btnPlay&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;btn-play&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;btnLoad&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;btn-load&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;urlInput&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;url-input&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;status&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;status&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;iconMax&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;icon-max&amp;#39;);
&amp;nbsp;&amp;nbsp;var&amp;nbsp;iconMin&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;icon-min&amp;#39;);

&amp;nbsp;&amp;nbsp;function&amp;nbsp;setStatus(msg)&amp;nbsp;{&amp;nbsp;status.textContent&amp;nbsp;=&amp;nbsp;msg;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;function&amp;nbsp;isFullscreen()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;!!(document.fullscreenElement&amp;nbsp;||&amp;nbsp;document.webkitFullscreenElement&amp;nbsp;||
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.webkitCurrentFullScreenElement);
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;function&amp;nbsp;updateIcon()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;fs&amp;nbsp;=&amp;nbsp;isFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iconMax.style.display&amp;nbsp;=&amp;nbsp;fs&amp;nbsp;?&amp;nbsp;&amp;#39;none&amp;#39;&amp;nbsp;:&amp;nbsp;&amp;#39;&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iconMin.style.display&amp;nbsp;=&amp;nbsp;fs&amp;nbsp;?&amp;nbsp;&amp;#39;&amp;#39;&amp;nbsp;:&amp;nbsp;&amp;#39;none&amp;#39;;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;//&amp;nbsp;最大化&amp;nbsp;/&amp;nbsp;退出全屏（兼容&amp;nbsp;iOS&amp;nbsp;Safari&amp;nbsp;的&amp;nbsp;video&amp;nbsp;原生全屏）
&amp;nbsp;&amp;nbsp;btnFs.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(isFullscreen())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(document.exitFullscreen)&amp;nbsp;document.exitFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;if&amp;nbsp;(document.webkitExitFullscreen)&amp;nbsp;document.webkitExitFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;if&amp;nbsp;(video.webkitExitFullscreen)&amp;nbsp;video.webkitExitFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(wrap.requestFullscreen)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wrap.requestFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;if&amp;nbsp;(wrap.webkitRequestFullscreen)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wrap.webkitRequestFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;if&amp;nbsp;(video.webkitEnterFullscreen)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;iOS&amp;nbsp;Safari:&amp;nbsp;只对&amp;nbsp;video&amp;nbsp;元素有效
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;video.webkitEnterFullscreen();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setStatus(&amp;#39;当前环境不支持全屏&amp;nbsp;API&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;[&amp;#39;fullscreenchange&amp;#39;,&amp;nbsp;&amp;#39;webkitfullscreenchange&amp;#39;].forEach(function&amp;nbsp;(ev)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.addEventListener(ev,&amp;nbsp;updateIcon);
&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;video.addEventListener(&amp;#39;webkitendfullscreen&amp;#39;,&amp;nbsp;updateIcon);

&amp;nbsp;&amp;nbsp;//&amp;nbsp;播放&amp;nbsp;/&amp;nbsp;暂停
&amp;nbsp;&amp;nbsp;btnPlay.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(video.paused)&amp;nbsp;video.play().catch(function&amp;nbsp;(e)&amp;nbsp;{&amp;nbsp;setStatus(&amp;#39;播放失败:&amp;nbsp;&amp;#39;&amp;nbsp;+&amp;nbsp;e.message);&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;video.pause();
&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;//&amp;nbsp;加载自定义地址
&amp;nbsp;&amp;nbsp;btnLoad.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;url&amp;nbsp;=&amp;nbsp;urlInput.value.trim();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!url)&amp;nbsp;{&amp;nbsp;setStatus(&amp;#39;请输入视频地址&amp;#39;);&amp;nbsp;return;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;video.src&amp;nbsp;=&amp;nbsp;url;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;video.load();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;video.play().catch(function&amp;nbsp;()&amp;nbsp;{});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setStatus(&amp;#39;已加载:&amp;nbsp;&amp;#39;&amp;nbsp;+&amp;nbsp;url);
&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;//&amp;nbsp;状态反馈
&amp;nbsp;&amp;nbsp;video.addEventListener(&amp;#39;playing&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{&amp;nbsp;setStatus(&amp;#39;播放中&amp;nbsp;&amp;#39;&amp;nbsp;+&amp;nbsp;video.videoWidth&amp;nbsp;+&amp;nbsp;&amp;#39;x&amp;#39;&amp;nbsp;+&amp;nbsp;video.videoHeight);&amp;nbsp;});
&amp;nbsp;&amp;nbsp;video.addEventListener(&amp;#39;pause&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{&amp;nbsp;setStatus(&amp;#39;已暂停&amp;#39;);&amp;nbsp;});
&amp;nbsp;&amp;nbsp;video.addEventListener(&amp;#39;error&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;err&amp;nbsp;=&amp;nbsp;video.error;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setStatus(&amp;#39;加载出错:&amp;nbsp;&amp;#39;&amp;nbsp;+&amp;nbsp;(err&amp;nbsp;?&amp;nbsp;&amp;#39;code&amp;nbsp;&amp;#39;&amp;nbsp;+&amp;nbsp;err.code&amp;nbsp;:&amp;nbsp;&amp;#39;未知错误&amp;#39;));
&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;video.addEventListener(&amp;#39;ended&amp;#39;,&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{&amp;nbsp;setStatus(&amp;#39;播放结束&amp;#39;);&amp;nbsp;});
})();
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;</description><pubDate>Mon, 10 Aug 2026 19:32:32 +0800</pubDate></item><item><title>HTML打包APK实现拍照、录像、录音和文件选择</title><link>https://www.h5pack.com/post/html-apk-camera-video-audio-file-picker.html</link><description>&lt;p&gt;HTML页面可以通过文件选择控件和浏览器媒体接口调用安卓设备的相机、摄像头、麦克风及文件选择器。完成页面代码后，再通过HTML一键打包APK工具配置相机和麦克风权限，即可生成支持拍照、录像、录音和文件选择的安卓APP。&lt;/p&gt;&lt;p&gt;如果你不了解HTML打包APK工具，想要进一步了解，可以查看官网：&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://html2apk.leapever.com/&quot;&gt;HTML一键打包APK工具官网&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;创建文件采集页面&lt;/h2&gt;&lt;p&gt;在HTML项目入口目录中创建 &lt;code&gt;index.html&lt;/code&gt;，加入拍摄照片、录制视频、录制音频和选择文件四个入口。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;拍摄照片：调用设备相机并优先进入后置摄像头拍照页面。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;录制视频：调用设备摄像头并进入视频录制页面。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;录制音频：申请麦克风权限，在网页内录制音频并生成可下载的音频文件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;选择文件：打开系统文件选择界面，并支持一次选择多个文件。也可以选择相机进行拍照或者录频&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;一个完整的html示例代码如下：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-html&quot;&gt;&amp;lt;!doctype&amp;nbsp;html&amp;gt;
&amp;lt;html&amp;nbsp;lang=&amp;quot;zh-CN&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;meta&amp;nbsp;charset=&amp;quot;utf-8&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;meta&amp;nbsp;name=&amp;quot;viewport&amp;quot;&amp;nbsp;content=&amp;quot;width=device-width,&amp;nbsp;initial-scale=1,&amp;nbsp;viewport-fit=cover&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;meta&amp;nbsp;name=&amp;quot;theme-color&amp;quot;&amp;nbsp;content=&amp;quot;#f4f1ea&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;title&amp;gt;移动端文件采集&amp;lt;/title&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;style&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:root&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color-scheme:&amp;nbsp;light;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--ink:&amp;nbsp;#18201d;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--muted:&amp;nbsp;#65706b;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--paper:&amp;nbsp;#f4f1ea;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--surface:&amp;nbsp;#fffdf8;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--line:&amp;nbsp;#d8d5cd;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--green:&amp;nbsp;#18634b;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--green-dark:&amp;nbsp;#104b39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--coral:&amp;nbsp;#e56f51;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--shadow:&amp;nbsp;0&amp;nbsp;12px&amp;nbsp;32px&amp;nbsp;rgba(24,&amp;nbsp;32,&amp;nbsp;29,&amp;nbsp;0.09);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;box-sizing:&amp;nbsp;border-box;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;letter-spacing:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-width:&amp;nbsp;320px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;100vh;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--ink);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;linear-gradient(rgba(24,&amp;nbsp;99,&amp;nbsp;75,&amp;nbsp;0.055)&amp;nbsp;1px,&amp;nbsp;transparent&amp;nbsp;1px),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;linear-gradient(90deg,&amp;nbsp;rgba(24,&amp;nbsp;99,&amp;nbsp;75,&amp;nbsp;0.055)&amp;nbsp;1px,&amp;nbsp;transparent&amp;nbsp;1px),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var(--paper);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-size:&amp;nbsp;24px&amp;nbsp;24px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-family:&amp;nbsp;&amp;quot;Noto&amp;nbsp;Sans&amp;nbsp;SC&amp;quot;,&amp;nbsp;&amp;quot;Microsoft&amp;nbsp;YaHei&amp;nbsp;UI&amp;quot;,&amp;nbsp;sans-serif;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;button,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;input&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font:&amp;nbsp;inherit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[hidden]&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;none&amp;nbsp;!important;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.shell&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;min(100%,&amp;nbsp;560px);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;100vh;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0&amp;nbsp;auto;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;max(24px,&amp;nbsp;env(safe-area-inset-top))&amp;nbsp;18px&amp;nbsp;max(32px,&amp;nbsp;env(safe-area-inset-bottom));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;relative;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;12px&amp;nbsp;4px&amp;nbsp;25px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header::after&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;absolute;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;right:&amp;nbsp;4px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bottom:&amp;nbsp;18px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;52px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;5px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--coral);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content:&amp;nbsp;&amp;quot;&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transform:&amp;nbsp;rotate(-3deg);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.eyebrow&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0&amp;nbsp;0&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--green);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;800;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text-transform:&amp;nbsp;uppercase;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h1&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-family:&amp;nbsp;&amp;quot;STSong&amp;quot;,&amp;nbsp;&amp;quot;SimSun&amp;quot;,&amp;nbsp;serif;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;clamp(32px,&amp;nbsp;10vw,&amp;nbsp;48px);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;700;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line-height:&amp;nbsp;1.08;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.subtitle&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max-width:&amp;nbsp;360px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;12px&amp;nbsp;0&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--muted);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line-height:&amp;nbsp;1.7;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.actions&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;grid;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grid-template-columns:&amp;nbsp;repeat(2,&amp;nbsp;minmax(0,&amp;nbsp;1fr));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gap:&amp;nbsp;10px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;relative;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-width:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;132px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--surface);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;box-shadow:&amp;nbsp;0&amp;nbsp;4px&amp;nbsp;12px&amp;nbsp;rgba(24,&amp;nbsp;32,&amp;nbsp;29,&amp;nbsp;0.035);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker:focus-within&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outline:&amp;nbsp;3px&amp;nbsp;solid&amp;nbsp;rgba(24,&amp;nbsp;99,&amp;nbsp;75,&amp;nbsp;0.2);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outline-offset:&amp;nbsp;2px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker&amp;nbsp;input&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position:&amp;nbsp;absolute;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;1px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;1px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;opacity:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pointer-events:&amp;nbsp;none;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker&amp;nbsp;label&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;132px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;17px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;pointer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex-direction:&amp;nbsp;column;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;justify-content:&amp;nbsp;space-between;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-webkit-tap-highlight-color:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker-button&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;132px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;17px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;inherit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;pointer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex-direction:&amp;nbsp;column;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;justify-content:&amp;nbsp;space-between;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text-align:&amp;nbsp;left;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-webkit-tap-highlight-color:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker&amp;nbsp;label:active,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker-button:active&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#f2f7f3;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.icon&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;grid;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;42px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;42px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;50%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--green);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;20px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;place-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker:nth-child(2)&amp;nbsp;.icon,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker:nth-child(4)&amp;nbsp;.icon&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--coral);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.label-title&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;block;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-bottom:&amp;nbsp;4px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;16px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;800;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.label-meta&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;block;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--muted);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;11px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text-overflow:&amp;nbsp;ellipsis;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space:&amp;nbsp;nowrap;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.result&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top:&amp;nbsp;18px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--surface);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;box-shadow:&amp;nbsp;var(--shadow);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;animation:&amp;nbsp;rise&amp;nbsp;240ms&amp;nbsp;ease-out;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.result-header&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;52px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;12px&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-bottom:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;align-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;justify-content:&amp;nbsp;space-between;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gap:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.result-header&amp;nbsp;h2&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;15px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.clear&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;34px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height:&amp;nbsp;34px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;50%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--ink);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;pointer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;20px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line-height:&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.file-list&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list-style:&amp;nbsp;none;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.file-list&amp;nbsp;li&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;flex;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gap:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;68px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;10px&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-top:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;align-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.file-list&amp;nbsp;li:first-child&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-top:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.file-info&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-width:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex:&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.file-name&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;block;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;700;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text-overflow:&amp;nbsp;ellipsis;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space:&amp;nbsp;nowrap;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.file-size&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;block;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top:&amp;nbsp;4px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--muted);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.download-button&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-width:&amp;nbsp;76px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;40px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;0&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--green);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;6px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--green);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;pointer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;800;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;flex-shrink:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.recorder&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top:&amp;nbsp;18px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;18px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--surface);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;box-shadow:&amp;nbsp;var(--shadow);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.recorder&amp;nbsp;h2&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0&amp;nbsp;0&amp;nbsp;6px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;18px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.recorder-status&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;42px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0&amp;nbsp;0&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--muted);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;13px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line-height:&amp;nbsp;1.6;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.recorder-controls&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;grid;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grid-template-columns:&amp;nbsp;1fr&amp;nbsp;1fr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gap:&amp;nbsp;10px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.recorder-controls&amp;nbsp;button,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.audio-fallback&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;46px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;var(--green);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;6px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#fff;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;var(--green);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;pointer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;800;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.recorder-controls&amp;nbsp;button:disabled&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor:&amp;nbsp;not-allowed;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;opacity:&amp;nbsp;0.45;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.audio-fallback&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;grid;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top:&amp;nbsp;10px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-color:&amp;nbsp;var(--line);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;var(--ink);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;transparent;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;13px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;place-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@keyframes&amp;nbsp;rise&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;from&amp;nbsp;{&amp;nbsp;opacity:&amp;nbsp;0;&amp;nbsp;transform:&amp;nbsp;translateY(8px);&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;to&amp;nbsp;{&amp;nbsp;opacity:&amp;nbsp;1;&amp;nbsp;transform:&amp;nbsp;translateY(0);&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@media&amp;nbsp;(min-width:&amp;nbsp;480px)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.shell&amp;nbsp;{&amp;nbsp;padding-inline:&amp;nbsp;26px;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.picker&amp;nbsp;label&amp;nbsp;{&amp;nbsp;min-height:&amp;nbsp;144px;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@media&amp;nbsp;(prefers-reduced-motion:&amp;nbsp;reduce)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.result&amp;nbsp;{&amp;nbsp;animation:&amp;nbsp;none;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;main&amp;nbsp;class=&amp;quot;shell&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;header&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;nbsp;class=&amp;quot;eyebrow&amp;quot;&amp;gt;Mobile&amp;nbsp;capture&amp;nbsp;lab&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h1&amp;gt;从设备中采集文件&amp;lt;/h1&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;nbsp;class=&amp;quot;subtitle&amp;quot;&amp;gt;点击一种方式，系统会打开对应的拍摄、录制或文件选择界面。&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/header&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;section&amp;nbsp;class=&amp;quot;actions&amp;quot;&amp;nbsp;aria-label=&amp;quot;文件采集方式&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;picker&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input&amp;nbsp;id=&amp;quot;camera&amp;quot;&amp;nbsp;type=&amp;quot;file&amp;quot;&amp;nbsp;accept=&amp;quot;image/*&amp;quot;&amp;nbsp;capture=&amp;quot;environment&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;label&amp;nbsp;for=&amp;quot;camera&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;nbsp;class=&amp;quot;icon&amp;quot;&amp;nbsp;aria-hidden=&amp;quot;true&amp;quot;&amp;gt;●&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-title&amp;quot;&amp;gt;拍摄照片&amp;lt;/span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-meta&amp;quot;&amp;gt;设备后置相机&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;picker&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input&amp;nbsp;id=&amp;quot;video&amp;quot;&amp;nbsp;type=&amp;quot;file&amp;quot;&amp;nbsp;accept=&amp;quot;video/*&amp;quot;&amp;nbsp;capture=&amp;quot;environment&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;label&amp;nbsp;for=&amp;quot;video&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;nbsp;class=&amp;quot;icon&amp;quot;&amp;nbsp;aria-hidden=&amp;quot;true&amp;quot;&amp;gt;▶&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-title&amp;quot;&amp;gt;录制视频&amp;lt;/span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-meta&amp;quot;&amp;gt;设备摄像头&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;picker&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;openRecorder&amp;quot;&amp;nbsp;class=&amp;quot;picker-button&amp;quot;&amp;nbsp;type=&amp;quot;button&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;nbsp;class=&amp;quot;icon&amp;quot;&amp;nbsp;aria-hidden=&amp;quot;true&amp;quot;&amp;gt;♪&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-title&amp;quot;&amp;gt;录制音频&amp;lt;/span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-meta&amp;quot;&amp;gt;设备麦克风&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;picker&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input&amp;nbsp;id=&amp;quot;files&amp;quot;&amp;nbsp;type=&amp;quot;file&amp;quot;&amp;nbsp;multiple&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;label&amp;nbsp;for=&amp;quot;files&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;nbsp;class=&amp;quot;icon&amp;quot;&amp;nbsp;aria-hidden=&amp;quot;true&amp;quot;&amp;gt;＋&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-title&amp;quot;&amp;gt;选择文件&amp;lt;/span&amp;gt;&amp;lt;span&amp;nbsp;class=&amp;quot;label-meta&amp;quot;&amp;gt;支持多选&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/section&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;section&amp;nbsp;id=&amp;quot;recorder&amp;quot;&amp;nbsp;class=&amp;quot;recorder&amp;quot;&amp;nbsp;aria-live=&amp;quot;polite&amp;quot;&amp;nbsp;hidden&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h2&amp;gt;麦克风录音&amp;lt;/h2&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;nbsp;id=&amp;quot;recorderStatus&amp;quot;&amp;nbsp;class=&amp;quot;recorder-status&amp;quot;&amp;gt;点击“开始录音”，并允许浏览器使用麦克风。&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;recorder-controls&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;startRecording&amp;quot;&amp;nbsp;type=&amp;quot;button&amp;quot;&amp;gt;开始录音&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;stopRecording&amp;quot;&amp;nbsp;type=&amp;quot;button&amp;quot;&amp;nbsp;disabled&amp;gt;停止并使用&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input&amp;nbsp;id=&amp;quot;audioFallback&amp;quot;&amp;nbsp;type=&amp;quot;file&amp;quot;&amp;nbsp;accept=&amp;quot;audio/*&amp;quot;&amp;nbsp;hidden&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;label&amp;nbsp;class=&amp;quot;audio-fallback&amp;quot;&amp;nbsp;for=&amp;quot;audioFallback&amp;quot;&amp;gt;无法录音？选择已有音频&amp;lt;/label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/section&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;section&amp;nbsp;id=&amp;quot;result&amp;quot;&amp;nbsp;class=&amp;quot;result&amp;quot;&amp;nbsp;aria-live=&amp;quot;polite&amp;quot;&amp;nbsp;hidden&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;result-header&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h2&amp;nbsp;id=&amp;quot;resultTitle&amp;quot;&amp;gt;处理完成&amp;lt;/h2&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;clearButton&amp;quot;&amp;nbsp;class=&amp;quot;clear&amp;quot;&amp;nbsp;type=&amp;quot;button&amp;quot;&amp;nbsp;aria-label=&amp;quot;清除选择&amp;quot;&amp;nbsp;title=&amp;quot;清除选择&amp;quot;&amp;gt;×&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ul&amp;nbsp;id=&amp;quot;fileList&amp;quot;&amp;nbsp;class=&amp;quot;file-list&amp;quot;&amp;gt;&amp;lt;/ul&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/section&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/main&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;lt;script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;inputs&amp;nbsp;=&amp;nbsp;document.querySelectorAll(&amp;#39;input[type=&amp;quot;file&amp;quot;]&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;result&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;result&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;resultTitle&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;resultTitle&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;fileList&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;fileList&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;clearButton&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;clearButton&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;openRecorder&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;openRecorder&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;recorderPanel&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;recorder&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;recorderStatus&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;recorderStatus&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;startRecording&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;startRecording&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;stopRecording&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;stopRecording&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;activeInput&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;microphoneStream&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;recordingAudioContext&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;recordingSource&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;recordingProcessor&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;recordingGain&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;pcmChunks&amp;nbsp;=&amp;nbsp;[];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;pcmSampleCount&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;isRecording&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;recordingTimer&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;recordingStartedAt&amp;nbsp;=&amp;nbsp;0;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;formatSize(bytes)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(bytes&amp;nbsp;===&amp;nbsp;0)&amp;nbsp;return&amp;nbsp;&amp;#39;0&amp;nbsp;B&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;units&amp;nbsp;=&amp;nbsp;[&amp;#39;B&amp;#39;,&amp;nbsp;&amp;#39;KB&amp;#39;,&amp;nbsp;&amp;#39;MB&amp;#39;,&amp;nbsp;&amp;#39;GB&amp;#39;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;unitIndex&amp;nbsp;=&amp;nbsp;Math.min(Math.floor(Math.log(bytes)&amp;nbsp;/&amp;nbsp;Math.log(1024)),&amp;nbsp;units.length&amp;nbsp;-&amp;nbsp;1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;`${(bytes&amp;nbsp;/&amp;nbsp;(1024&amp;nbsp;**&amp;nbsp;unitIndex)).toFixed(unitIndex&amp;nbsp;?&amp;nbsp;1&amp;nbsp;:&amp;nbsp;0)}&amp;nbsp;${units[unitIndex]}`;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;clearSelection()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(activeInput)&amp;nbsp;activeInput.value&amp;nbsp;=&amp;nbsp;&amp;#39;&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activeInput&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fileList.replaceChildren();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result.hidden&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;downloadFile(file)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;reader&amp;nbsp;=&amp;nbsp;new&amp;nbsp;FileReader();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reader.addEventListener(&amp;#39;load&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;link&amp;nbsp;=&amp;nbsp;document.createElement(&amp;#39;a&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;link.href&amp;nbsp;=&amp;nbsp;reader.result;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;link.download&amp;nbsp;=&amp;nbsp;file.name&amp;nbsp;||&amp;nbsp;`文件_${Date.now()}`;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.appendChild(link);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;link.click();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.removeChild(link);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reader.addEventListener(&amp;#39;error&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resultTitle.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;下载失败，请重试&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reader.readAsDataURL(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;displayFiles(files,&amp;nbsp;input&amp;nbsp;=&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!files.length)&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(activeInput&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;activeInput&amp;nbsp;!==&amp;nbsp;input)&amp;nbsp;activeInput.value&amp;nbsp;=&amp;nbsp;&amp;#39;&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activeInput&amp;nbsp;=&amp;nbsp;input;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resultTitle.textContent&amp;nbsp;=&amp;nbsp;files.length&amp;nbsp;&amp;gt;&amp;nbsp;1&amp;nbsp;?&amp;nbsp;`${files.length}&amp;nbsp;个文件处理完成`&amp;nbsp;:&amp;nbsp;&amp;#39;处理完成&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fileList.replaceChildren(...files.map((file)&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;item&amp;nbsp;=&amp;nbsp;document.createElement(&amp;#39;li&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;info&amp;nbsp;=&amp;nbsp;document.createElement(&amp;#39;span&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;name&amp;nbsp;=&amp;nbsp;document.createElement(&amp;#39;span&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;size&amp;nbsp;=&amp;nbsp;document.createElement(&amp;#39;span&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;downloadButton&amp;nbsp;=&amp;nbsp;document.createElement(&amp;#39;button&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info.className&amp;nbsp;=&amp;nbsp;&amp;#39;file-info&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name.className&amp;nbsp;=&amp;nbsp;&amp;#39;file-name&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name.textContent&amp;nbsp;=&amp;nbsp;file.name;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size.className&amp;nbsp;=&amp;nbsp;&amp;#39;file-size&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size.textContent&amp;nbsp;=&amp;nbsp;formatSize(file.size);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;downloadButton.className&amp;nbsp;=&amp;nbsp;&amp;#39;download-button&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;downloadButton.type&amp;nbsp;=&amp;nbsp;&amp;#39;button&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;downloadButton.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;↓&amp;nbsp;下载&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;downloadButton.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;downloadFile(file));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info.append(name,&amp;nbsp;size);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item.append(info,&amp;nbsp;downloadButton);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;item;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result.hidden&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result.scrollIntoView({&amp;nbsp;behavior:&amp;nbsp;&amp;#39;smooth&amp;#39;,&amp;nbsp;block:&amp;nbsp;&amp;#39;nearest&amp;#39;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;stopMicrophone()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(recordingTimer)&amp;nbsp;clearInterval(recordingTimer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingTimer&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;isRecording&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(recordingProcessor)&amp;nbsp;recordingProcessor.disconnect();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(recordingSource)&amp;nbsp;recordingSource.disconnect();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(recordingGain)&amp;nbsp;recordingGain.disconnect();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingProcessor&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingSource&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingGain&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(microphoneStream)&amp;nbsp;microphoneStream.getTracks().forEach((track)&amp;nbsp;=&amp;gt;&amp;nbsp;track.stop());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;microphoneStream&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(recordingAudioContext&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;recordingAudioContext.state&amp;nbsp;!==&amp;nbsp;&amp;#39;closed&amp;#39;)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingAudioContext.close().catch(()&amp;nbsp;=&amp;gt;&amp;nbsp;{});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingAudioContext&amp;nbsp;=&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;createWavFile(chunks,&amp;nbsp;sampleCount,&amp;nbsp;sampleRate)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;buffer&amp;nbsp;=&amp;nbsp;new&amp;nbsp;ArrayBuffer(44&amp;nbsp;+&amp;nbsp;sampleCount&amp;nbsp;*&amp;nbsp;2);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;view&amp;nbsp;=&amp;nbsp;new&amp;nbsp;DataView(buffer);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;writeText(offset,&amp;nbsp;text)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(let&amp;nbsp;index&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;index&amp;nbsp;&amp;lt;&amp;nbsp;text.length;&amp;nbsp;index&amp;nbsp;+=&amp;nbsp;1)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint8(offset&amp;nbsp;+&amp;nbsp;index,&amp;nbsp;text.charCodeAt(index));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writeText(0,&amp;nbsp;&amp;#39;RIFF&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint32(4,&amp;nbsp;36&amp;nbsp;+&amp;nbsp;sampleCount&amp;nbsp;*&amp;nbsp;2,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writeText(8,&amp;nbsp;&amp;#39;WAVE&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writeText(12,&amp;nbsp;&amp;#39;fmt&amp;nbsp;&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint32(16,&amp;nbsp;16,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint16(20,&amp;nbsp;1,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint16(22,&amp;nbsp;1,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint32(24,&amp;nbsp;sampleRate,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint32(28,&amp;nbsp;sampleRate&amp;nbsp;*&amp;nbsp;2,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint16(32,&amp;nbsp;2,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint16(34,&amp;nbsp;16,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writeText(36,&amp;nbsp;&amp;#39;data&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setUint32(40,&amp;nbsp;sampleCount&amp;nbsp;*&amp;nbsp;2,&amp;nbsp;true);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;offset&amp;nbsp;=&amp;nbsp;44;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;chunks.forEach((chunk)&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(let&amp;nbsp;index&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;index&amp;nbsp;&amp;lt;&amp;nbsp;chunk.length;&amp;nbsp;index&amp;nbsp;+=&amp;nbsp;1)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;sample&amp;nbsp;=&amp;nbsp;Math.max(-1,&amp;nbsp;Math.min(1,&amp;nbsp;chunk[index]));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.setInt16(offset,&amp;nbsp;sample&amp;nbsp;&amp;lt;&amp;nbsp;0&amp;nbsp;?&amp;nbsp;sample&amp;nbsp;*&amp;nbsp;0x8000&amp;nbsp;:&amp;nbsp;sample&amp;nbsp;*&amp;nbsp;0x7fff,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;offset&amp;nbsp;+=&amp;nbsp;2;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;new&amp;nbsp;File([buffer],&amp;nbsp;`recording-${Date.now()}.wav`,&amp;nbsp;{&amp;nbsp;type:&amp;nbsp;&amp;#39;audio/wav&amp;#39;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inputs.forEach((input)&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;input.addEventListener(&amp;#39;change&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;files&amp;nbsp;=&amp;nbsp;Array.from(input.files&amp;nbsp;||&amp;nbsp;[]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;displayFiles(files,&amp;nbsp;input);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;openRecorder.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderPanel.hidden&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderPanel.scrollIntoView({&amp;nbsp;behavior:&amp;nbsp;&amp;#39;smooth&amp;#39;,&amp;nbsp;block:&amp;nbsp;&amp;#39;nearest&amp;#39;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startRecording.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;async&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;AudioContextClass&amp;nbsp;=&amp;nbsp;window.AudioContext&amp;nbsp;||&amp;nbsp;window.webkitAudioContext;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!navigator.mediaDevices?.getUserMedia&amp;nbsp;||&amp;nbsp;!AudioContextClass)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderStatus.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;当前浏览器不支持网页录音，请使用下方按钮选择已有音频。&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;microphoneStream&amp;nbsp;=&amp;nbsp;await&amp;nbsp;navigator.mediaDevices.getUserMedia({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;audio:&amp;nbsp;{&amp;nbsp;channelCount:&amp;nbsp;1,&amp;nbsp;echoCancellation:&amp;nbsp;true,&amp;nbsp;noiseSuppression:&amp;nbsp;true&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingAudioContext&amp;nbsp;=&amp;nbsp;new&amp;nbsp;AudioContextClass();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;recordingAudioContext.resume();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingSource&amp;nbsp;=&amp;nbsp;recordingAudioContext.createMediaStreamSource(microphoneStream);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingProcessor&amp;nbsp;=&amp;nbsp;recordingAudioContext.createScriptProcessor(4096,&amp;nbsp;1,&amp;nbsp;1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingGain&amp;nbsp;=&amp;nbsp;recordingAudioContext.createGain();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingGain.gain.value&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pcmChunks&amp;nbsp;=&amp;nbsp;[];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pcmSampleCount&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;isRecording&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingProcessor.onaudioprocess&amp;nbsp;=&amp;nbsp;(event)&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!isRecording)&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;samples&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Float32Array(event.inputBuffer.length);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event.inputBuffer.copyFromChannel(samples,&amp;nbsp;0);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pcmChunks.push(samples);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pcmSampleCount&amp;nbsp;+=&amp;nbsp;samples.length;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingSource.connect(recordingProcessor);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingProcessor.connect(recordingGain);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingGain.connect(recordingAudioContext.destination);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingStartedAt&amp;nbsp;=&amp;nbsp;Date.now();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderStatus.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;正在录音&amp;nbsp;00:00&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recordingTimer&amp;nbsp;=&amp;nbsp;setInterval(()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;elapsed&amp;nbsp;=&amp;nbsp;Math.floor((Date.now()&amp;nbsp;-&amp;nbsp;recordingStartedAt)&amp;nbsp;/&amp;nbsp;1000);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;minutes&amp;nbsp;=&amp;nbsp;String(Math.floor(elapsed&amp;nbsp;/&amp;nbsp;60)).padStart(2,&amp;nbsp;&amp;#39;0&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;seconds&amp;nbsp;=&amp;nbsp;String(elapsed&amp;nbsp;%&amp;nbsp;60).padStart(2,&amp;nbsp;&amp;#39;0&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderStatus.textContent&amp;nbsp;=&amp;nbsp;`正在录音&amp;nbsp;${minutes}:${seconds}`;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&amp;nbsp;1000);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startRecording.disabled&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopRecording.disabled&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;catch&amp;nbsp;(error)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopMicrophone();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;insecure&amp;nbsp;=&amp;nbsp;!window.isSecureContext;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderStatus.textContent&amp;nbsp;=&amp;nbsp;insecure
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;?&amp;nbsp;&amp;#39;浏览器只允许&amp;nbsp;HTTPS&amp;nbsp;页面使用麦克风，请通过&amp;nbsp;HTTPS&amp;nbsp;打开本页。&amp;#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&amp;#39;未能使用麦克风，请检查浏览器的网站麦克风权限。&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopRecording.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!isRecording&amp;nbsp;||&amp;nbsp;!recordingAudioContext&amp;nbsp;||&amp;nbsp;!pcmSampleCount)&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;isRecording&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;sampleRate&amp;nbsp;=&amp;nbsp;recordingAudioContext.sampleRate;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;duration&amp;nbsp;=&amp;nbsp;pcmSampleCount&amp;nbsp;/&amp;nbsp;sampleRate;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;recording&amp;nbsp;=&amp;nbsp;createWavFile(pcmChunks,&amp;nbsp;pcmSampleCount,&amp;nbsp;sampleRate);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopMicrophone();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;displayFiles([recording]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recorderStatus.textContent&amp;nbsp;=&amp;nbsp;`录音处理完成（${duration.toFixed(1)}&amp;nbsp;秒），可在下方下载。`;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startRecording.disabled&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopRecording.disabled&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clearButton.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;clearSelection);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.addEventListener(&amp;#39;pagehide&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopMicrophone();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;&lt;p&gt;页面中的拍照和录像入口可以分别使用带有 &lt;code&gt;capture&lt;/code&gt; 属性的文件控件。拍照入口设置 &lt;code&gt;accept=&amp;quot;image/*&amp;quot;&lt;/code&gt;，录像入口设置 &lt;code&gt;accept=&amp;quot;video/*&amp;quot;&lt;/code&gt;，安卓APP会根据文件类型打开对应的系统采集页面。&lt;/p&gt;&lt;p&gt;拍摄照片：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-html&quot;&gt;&amp;lt;input&amp;nbsp;type=&amp;quot;file&amp;quot;&amp;nbsp;accept=&amp;quot;image/*&amp;quot;&amp;nbsp;capture=&amp;quot;environment&amp;quot;&amp;nbsp;/&amp;gt;&lt;/pre&gt;&lt;p&gt;录制视频：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-html&quot;&gt;&amp;lt;input&amp;nbsp;type=&amp;quot;file&amp;quot;&amp;nbsp;accept=&amp;quot;video/*&amp;quot;&amp;nbsp;capture=&amp;quot;environment&amp;quot;&amp;nbsp;/&amp;gt;&lt;/pre&gt;&lt;p&gt;音频录制可以通过 &lt;code&gt;navigator.mediaDevices.getUserMedia()&lt;/code&gt; 获取麦克风音频流，再使用浏览器音频接口处理并生成音频文件。普通文件入口不设置 &lt;code&gt;capture&lt;/code&gt;，因此会保留系统提供的文件、照片和视频选择方式。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1786193046142_6f1c623d.png&quot; alt=&quot;拍照录像录音和文件选择页面&quot;/&gt;&lt;/p&gt;&lt;h2&gt;打包APK并配置权限&lt;/h2&gt;&lt;p&gt;打开HTML一键打包APK工具，选择包含 &lt;code&gt;index.html&lt;/code&gt; 的项目目录，填写应用名称、包名等打包信息。&lt;/p&gt;&lt;p&gt;在权限设置中勾选“相机权限”和“麦克风权限”：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;相机权限用于拍摄照片、录制视频以及网页调用摄像头。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;麦克风权限用于网页录音；录制带声音的视频时也需要该权限。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;普通文件选择通过安卓系统文件选择器完成，用户只会授权当前选择的文件。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1786193046315_b3772f1b.png&quot; alt=&quot;打包APK时配置相机和麦克风权限&quot;/&gt;&lt;/p&gt;&lt;p&gt;确认配置后开始打包，等待工具生成APK文件。&lt;/p&gt;&lt;h2&gt;安装并测试功能&lt;/h2&gt;&lt;p&gt;将生成的APK安装到安卓手机，依次测试页面中的四个入口：&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;点击“拍摄照片”，确认APP直接打开相机拍照页面。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;点击“录制视频”，确认APP直接打开视频录制页面，并且能够正常保存视频。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;点击“录制音频”，首次使用时允许APP访问麦克风，停止录音后确认页面能够显示并下载录音文件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;点击“选择文件”，确认系统文件选择界面正常打开，并且可以选择一个或多个文件。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;不同品牌手机使用的相机和文件管理应用可能不同，因此系统界面的样式会有差异。&lt;code&gt;capture&lt;/code&gt; 属性用于告诉安卓当前需要拍照还是录像，但最终的采集界面由手机系统和默认相机应用提供。&lt;/p&gt;&lt;p&gt;如果拍照或录像入口没有打开对应页面，请先检查APP的相机权限；如果网页无法开始录音，请检查麦克风权限。对于在线页面，网页录音通常还要求通过HTTPS加载；打包到APP内的本地页面则由WebView和APP权限共同控制。&lt;/p&gt;</description><pubDate>Sat, 08 Aug 2026 20:44:03 +0800</pubDate></item><item><title>HTML打包APK实现二维码扫码功能教程</title><link>https://www.h5pack.com/post/html-apk-qrcode-scanner-h5pack.html</link><description>&lt;p&gt;在HTML项目中，可以使用 &lt;code&gt;html5-qrcode&lt;/code&gt; 调用手机摄像头并识别二维码。完成页面代码后，再通过HTML一键打包APK工具勾选相机权限，即可生成支持扫码的安卓APP。&lt;/p&gt;&lt;p&gt;如果你不了解HTML打包APK工具, 想要进一步了解, 可以查看官网:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://html2apk.leapever.com/&quot;&gt;HTML一键打包APK工具官网&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;创建扫码页面&lt;/h2&gt;&lt;p&gt;在HTML项目入口目录中创建 &lt;code&gt;index.html&lt;/code&gt;，写入以下代码。页面点击“开始扫码”后会申请摄像头权限，识别成功时停止摄像头并显示二维码内容。&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-html&quot;&gt;&amp;lt;!doctype&amp;nbsp;html&amp;gt;
&amp;lt;html&amp;nbsp;lang=&amp;quot;zh-CN&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;head&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;meta&amp;nbsp;charset=&amp;quot;UTF-8&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;meta&amp;nbsp;name=&amp;quot;viewport&amp;quot;&amp;nbsp;content=&amp;quot;width=device-width,&amp;nbsp;initial-scale=1,&amp;nbsp;viewport-fit=cover&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;title&amp;gt;二维码扫码&amp;lt;/title&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;script&amp;nbsp;src=&amp;quot;https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;style&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;box-sizing:&amp;nbsp;border-box;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;100vh;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;20px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;grid;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;place-items:&amp;nbsp;center;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-family:&amp;nbsp;&amp;#39;Microsoft&amp;nbsp;YaHei&amp;#39;,&amp;nbsp;sans-serif;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#f4f7f5;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#17221c;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;main&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;min(100%,&amp;nbsp;440px);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h1&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0&amp;nbsp;0&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;30px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin:&amp;nbsp;0&amp;nbsp;0&amp;nbsp;18px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#526159;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#reader&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width:&amp;nbsp;100%;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;280px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow:&amp;nbsp;hidden;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;1px&amp;nbsp;solid&amp;nbsp;#cad4ce;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;8px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#101511;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#reader&amp;nbsp;video&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;object-fit:&amp;nbsp;cover;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.actions&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display:&amp;nbsp;grid;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grid-template-columns:&amp;nbsp;1fr&amp;nbsp;1fr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gap:&amp;nbsp;10px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top:&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;button&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;48px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border:&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;border-radius:&amp;nbsp;6px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding:&amp;nbsp;0&amp;nbsp;16px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font:&amp;nbsp;inherit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-weight:&amp;nbsp;700;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#startButton&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#197447;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;white;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#stopButton&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background:&amp;nbsp;#dfe6e2;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#26352d;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;button:disabled&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;opacity:&amp;nbsp;0.5;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#status&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;min-height:&amp;nbsp;24px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top:&amp;nbsp;12px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size:&amp;nbsp;14px;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:&amp;nbsp;#526159;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/style&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/head&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;body&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;main&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h1&amp;gt;二维码扫码&amp;lt;/h1&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;gt;点击开始后，将摄像头对准二维码。&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;id=&amp;quot;reader&amp;quot;&amp;nbsp;aria-label=&amp;quot;摄像头扫码区域&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;class=&amp;quot;actions&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;startButton&amp;quot;&amp;nbsp;type=&amp;quot;button&amp;quot;&amp;gt;开始扫码&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button&amp;nbsp;id=&amp;quot;stopButton&amp;quot;&amp;nbsp;type=&amp;quot;button&amp;quot;&amp;nbsp;disabled&amp;gt;停止扫码&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;nbsp;id=&amp;quot;status&amp;quot;&amp;nbsp;role=&amp;quot;status&amp;quot;&amp;gt;等待开始&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/main&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;reader&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Html5Qrcode(&amp;#39;reader&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;startButton&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;startButton&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;stopButton&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;stopButton&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;status&amp;nbsp;=&amp;nbsp;document.getElementById(&amp;#39;status&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;isScanning&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;resultHandled&amp;nbsp;=&amp;nbsp;false;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;function&amp;nbsp;stopScanning()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!isScanning)&amp;nbsp;return;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;reader.stop();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;isScanning&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startButton.disabled&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopButton.disabled&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;扫码已停止&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;function&amp;nbsp;startScanning()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startButton.disabled&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;正在请求摄像头权限...&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resultHandled&amp;nbsp;=&amp;nbsp;false;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;reader.start(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;facingMode:&amp;nbsp;&amp;#39;environment&amp;#39;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;fps:&amp;nbsp;10,&amp;nbsp;qrbox:&amp;nbsp;{&amp;nbsp;width:&amp;nbsp;240,&amp;nbsp;height:&amp;nbsp;240&amp;nbsp;}&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;decodedText&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(resultHandled)&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resultHandled&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;await&amp;nbsp;stopScanning();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(decodedText);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;isScanning&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopButton.disabled&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;正在扫描...&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;catch&amp;nbsp;(error)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startButton.disabled&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status.textContent&amp;nbsp;=&amp;nbsp;&amp;#39;无法打开摄像头，请检查相机权限。&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;console.error(error);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startButton.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;startScanning);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopButton.addEventListener(&amp;#39;click&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stopScanning().catch(console.error);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.addEventListener(&amp;#39;pagehide&amp;#39;,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(isScanning)&amp;nbsp;reader.stop().catch(()&amp;nbsp;=&amp;gt;&amp;nbsp;{});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;&lt;p&gt;示例通过 CDN 加载 &lt;code&gt;html5-qrcode&lt;/code&gt;。如果APP需要完全离线运行，请提前下载 &lt;code&gt;html5-qrcode.min.js&lt;/code&gt; 放入项目目录，并将页面中的脚本地址改为本地相对路径。&lt;/p&gt;&lt;h2&gt;打包APK并勾选相机权限&lt;/h2&gt;&lt;p&gt;打开HTML一键打包APK工具，选择包含 &lt;code&gt;index.html&lt;/code&gt; 的项目目录，填写应用名称、包名等打包信息。在权限设置中勾选“相机权限”，否则APP无法调用手机摄像头。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1786108503465_d2a85958.png&quot; alt=&quot;打包APK时勾选相机权限&quot;/&gt;&lt;/p&gt;&lt;p&gt;确认配置后开始打包，等待工具生成APK文件。&lt;/p&gt;&lt;h2&gt;安装并测试扫码&lt;/h2&gt;&lt;p&gt;将生成的APK安装到安卓手机。首次点击“开始扫码”时，系统会弹出相机授权提示，选择允许后，将摄像头对准二维码。识别成功后，页面会停止扫描并弹出二维码中的文字或链接。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1786108503630_5c3900e0.png&quot; alt=&quot;打包后的APP扫码运行效果&quot;/&gt;&lt;/p&gt;&lt;p&gt;如果页面提示无法打开摄像头，请先在手机的应用权限设置中确认相机权限已经允许。扫码页面使用 CDN 脚本时，还需要确保手机能够正常访问网络；改用本地脚本后则不受此限制。&lt;/p&gt;</description><pubDate>Fri, 07 Aug 2026 21:15:01 +0800</pubDate></item><item><title>恒盾C#混淆加密大师选项详解</title><link>https://www.h5pack.com/post/hengdun-csharp-obfuscator-options-guide.html</link><description>&lt;p&gt;恒盾C#混淆加密大师提供了四类保护选项：基本保护、垃圾代码注入、代码混淆和重命名。它们解决的问题各有侧重——有的阻止调试和反编译，有的增加反编译代码的理解难度，还有的会直接改变类型、函数和字段的名称，使攻击者难以追踪业务逻辑。&lt;/p&gt;&lt;p&gt;实际应用中，不建议不加区分地勾选所有选项。更好的做法是先理解每类功能的作用，再根据项目类型（如 DLL、控制台应用、WinForms、WPF 等）逐步启用，并在每次调整后进行启动和核心功能测试。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844593725_469744ee.png&quot; alt=&quot;界面&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://csharpobf.leapever.com/&quot;&gt;官方网址&lt;/a&gt;&lt;/p&gt;&lt;!-- truncate --&gt;&lt;h2&gt;四类混淆选项的核心作用&lt;/h2&gt;&lt;p&gt;软件中的选项可以分为四类：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;基本保护选项&lt;/strong&gt;：针对调试器、反编译工具、程序篡改和虚拟机环境进行防御。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;注入功能选项&lt;/strong&gt;：向程序集注入无用字段、指令、函数、类型或字符串，增加静态分析的干扰。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;混淆功能选项&lt;/strong&gt;：改变代码、数据或程序集结构，让反编译结果更难还原。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;重命名选项&lt;/strong&gt;：修改 Module、字段、函数、命名空间、参数、类型和 Assembly 等标识符。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这四类功能可以组合使用。重命名降低代码可读性，字符串和流程类混淆保护关键逻辑，基本保护则针对常见分析工具和运行环境形成额外防线。&lt;/p&gt;&lt;h2&gt;基本保护选项详解&lt;/h2&gt;&lt;p&gt;基本保护主要面向调试、反编译、篡改和运行环境检测。部分功能在检测到特定行为时会终止程序，因此启用后必须在目标用户的真实环境中测试。&lt;/p&gt;&lt;h3&gt;防调试、防DnSpy与防断点&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防调试&lt;/strong&gt;：检测 Visual Studio 或其他第三方调试工具附加到程序的行为，发现后自动退出。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防DnSpy&lt;/strong&gt;：专门检测 DnSpy 动态调试，发现后退出。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防断点&lt;/strong&gt;：检测程序运行中异常长时间停顿，用于防止通过断点逐步跟踪代码。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这三个选项都与运行时分析相关，适合保护授权校验、关键算法和商业逻辑。由于性能较低设备、特殊运行环境或正常诊断可能影响检测，建议在测试版中启用后覆盖不同配置的设备验证。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844593913_165f9483.png&quot; alt=&quot;防DnSpy处理效果&quot;/&gt;&lt;/p&gt;&lt;h3&gt;防ILDasm、防ILSpy与防de4dot&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防ILDasm&lt;/strong&gt;：阻止系统 ILDasm 工具正常反编译处理后的 DLL 或 EXE。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防ILSpy&lt;/strong&gt;：让处理后的程序集无法被 ILSpy 正常解析。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防de4dot&lt;/strong&gt;：干扰 de4dot 对程序集执行自动反混淆。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这组功能主要用于阻止常见的静态分析和自动还原工具。配合重命名、流程混淆、字符串加密等功能，可让分析者既难打开程序集，也难理解已反编译的代码。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594044_d5e20adf.png&quot; alt=&quot;防ILDasm处理效果&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594145_082e764f.png&quot; alt=&quot;防de4dot处理效果&quot;/&gt;&lt;/p&gt;&lt;h3&gt;防篡改与加壳（仅限 EXE）&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;防篡改&lt;/strong&gt;：校验 EXE 是否被修改，改动后无法正常运行。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;加壳&lt;/strong&gt;：把原程序加密并内嵌到外层 EXE 中，避免静态反编译工具直接查看代码。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这两个选项只适用于 EXE。防篡改适合需保证文件完整性的桌面程序；加壳适合希望隐藏原始程序集的应用。处理后需重新检查数字签名、杀毒软件兼容性、更新程序和安装包流程。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594260_95b19b59.png&quot; alt=&quot;EXE加壳处理效果&quot;/&gt;&lt;/p&gt;&lt;h3&gt;防虚拟机&lt;/h3&gt;&lt;p&gt;防虚拟机会检测程序是否运行在虚拟机中，检测到后停止运行。该功能适合明确禁止虚拟机运行的应用，但不适合在云桌面、虚拟化服务器、自动化测试机或沙箱中使用的软件。启用前需确认用户部署环境。&lt;/p&gt;&lt;h2&gt;注入功能选项&lt;/h2&gt;&lt;p&gt;注入功能不替代关键代码加密，而是通过增加干扰内容让反编译后的程序集结构更复杂。&lt;/p&gt;&lt;h3&gt;垃圾域、垃圾函数与垃圾类型&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;垃圾域&lt;/strong&gt;：向类型中加入多个无用字段。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;垃圾函数&lt;/strong&gt;：加入不参与业务的无用函数。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;垃圾类型&lt;/strong&gt;：加入额外的无用类型。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这些选项让反编译工具显示更多成员，使分析者更难定位真实业务代码。对体积敏感的项目，应比较处理前后的文件大小和加载表现。&lt;/p&gt;&lt;h3&gt;垃圾空指令与垃圾字符串&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;垃圾空指令&lt;/strong&gt;：在 IL 指令中注入无用指令，增加反编译代码阅读难度。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;垃圾字符串&lt;/strong&gt;：加入无用字符串，干扰通过字符串搜索定位关键逻辑。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;垃圾空指令适合配合流程混淆；垃圾字符串适合干扰对接口地址、提示文本或关键字的检索。它们的主要作用是增加分析成本。&lt;/p&gt;&lt;h2&gt;混淆功能选项&lt;/h2&gt;&lt;p&gt;混淆功能处理程序集信息、代码流程、常量、调用关系、函数体和资源等。部分选项改变范围大，建议从常用选项开始逐步增加保护强度。&lt;/p&gt;&lt;h3&gt;程序集与文件结构混淆&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;文件信息混淆&lt;/strong&gt;：修改程序内部名称和 Assembly 信息。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;文件时间混淆&lt;/strong&gt;：修改加密文件的时间戳。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DOS头混淆&lt;/strong&gt;：修改 EXE 的 DOS 头内容。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;混淆引用列表&lt;/strong&gt;：处理程序集引用列表，使依赖关系难理解。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;加密资源文件&lt;/strong&gt;：加密资源，防止直接查看。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;若程序依赖程序集名称、文件版本、反射、插件扫描或资源加载路径，启用后需重点验证。加密资源文件还需测试图片、语言资源等能否正常读取。&lt;/p&gt;&lt;h3&gt;流程与函数调用混淆&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;流程混淆&lt;/strong&gt;：打乱函数内部指令并增加跳转，使反编译后控制流程难理解。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;函数调用混淆&lt;/strong&gt;：通过函数 token 调用目标函数，降低调用关系可读性。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;链式函数混淆&lt;/strong&gt;：把一次函数调用转换为多层嵌套调用。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;异步混淆&lt;/strong&gt;：把部分代码转换为异步调用形式。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;错误函数体混淆&lt;/strong&gt;：加入错误指令干扰静态分析。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;流程混淆通常是核心算法的首选。对于 UI 线程、启动入口、COM 调用、反射调用等敏感函数，应逐项启用并测试。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594396_14bf5583.png&quot; alt=&quot;流程混淆前后对比&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594519_4ca58768.png&quot; alt=&quot;函数调用混淆效果&quot;/&gt;&lt;/p&gt;&lt;h3&gt;字符串保护&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;字符串加密&lt;/strong&gt;：加密字符串，避免静态分析找到关键文本。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;字符串拆分&lt;/strong&gt;：把一个字符串拆分为多个组合，降低直接搜索效果。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;字符串隐藏&lt;/strong&gt;：加密存放到原生函数中，反编译工具无法直接获取。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;字符串加密适合保护接口地址、协议字段等；字符串拆分干扰简单检索；字符串隐藏保护强度更高。配置文件中的密码、令牌等敏感凭据不应仅依赖混淆。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594628_a9e84529.png&quot; alt=&quot;字符串加密效果&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594755_8bf3fd8b.png&quot; alt=&quot;字符串拆分效果&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594865_7d8c7fc1.png&quot; alt=&quot;字符串隐藏效果&quot;/&gt;&lt;/p&gt;&lt;h3&gt;数字、布尔值与小数保护&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;布尔混淆&lt;/strong&gt;：把布尔值转换为更难识别的类型。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;数字混淆&lt;/strong&gt;：整型数字转换为复杂运算，隐藏常量。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;数字隐藏&lt;/strong&gt;：整型数字加密存放到原生函数中。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;小数混淆&lt;/strong&gt;：加密小数，避免直接看到原始值。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;适合保护算法常量、状态标识等。涉及浮点精度、边界值或高频计算的代码需重点验证。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844594981_2b2be063.png&quot; alt=&quot;数字混淆效果&quot;/&gt;&lt;/p&gt;&lt;h3&gt;函数体隐藏与原生化EXE&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;函数体隐藏&lt;/strong&gt;：加密函数体，反编译工具无法直接查看内部代码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;原生化EXE&lt;/strong&gt;：把 EXE 转换为原生程序，C# 反编译工具无法分析 IL 代码。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;适合保护核心实现。函数体隐藏针对重要算法；原生化EXE改变程序形态，仅用于 EXE。启用后需完整测试启动、异常处理、依赖加载等。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844595103_c94f9466.png&quot; alt=&quot;函数体隐藏效果&quot;/&gt;&lt;/p&gt;&lt;h2&gt;重命名选项解析&lt;/h2&gt;&lt;p&gt;重命名是 C# 混淆中最直观的保护，把业务含义标识符替换为难以理解的新名称。&lt;/p&gt;&lt;h3&gt;重命名模式选择&lt;/h3&gt;&lt;p&gt;软件提供五种模式：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;字母数字模式&lt;/strong&gt;：常规字母数字组合，适合大多数项目。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;UUID模式&lt;/strong&gt;：类似 UUID 的长名称，增加阅读难度。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;特殊字符模式&lt;/strong&gt;：使用特殊字符，追求更高阅读干扰。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Base64模式&lt;/strong&gt;：Base64 风格字符串。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;英文单词模式&lt;/strong&gt;：英文单词替换，表面可读但不保留真实含义。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;日常可从字母数字模式开始；若外部工具对字符有限制，应避免特殊字符模式。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844595236_410e52e4.png&quot; alt=&quot;字母数字重命名模式&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844595383_909d1275.png&quot; alt=&quot;UUID重命名模式&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844595536_e77bad2a.png&quot; alt=&quot;特殊字符重命名模式&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844595649_16204621.png&quot; alt=&quot;Base64重命名模式&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785844595778_b5af771f.png&quot; alt=&quot;英文单词重命名模式&quot;/&gt;&lt;/p&gt;&lt;h3&gt;可重命名的对象&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Module重命名&lt;/strong&gt;：修改全局 Module 名称。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;域重命名&lt;/strong&gt;：修改字段名称。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;函数重命名&lt;/strong&gt;：修改方法名称。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;命名空间重命名&lt;/strong&gt;：修改命名空间。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;参数重命名&lt;/strong&gt;：修改函数参数名称。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;类型重命名&lt;/strong&gt;：修改类、结构体等名称。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assembly重命名&lt;/strong&gt;：修改程序集名称。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;普通内部代码可优先启用字段、函数、参数和类型重命名。涉及反射、序列化、XAML 等时，名称可能是运行时契约，需确认框架是否按字符串查找成员。Assembly 重命名可能影响依赖程序集和插件加载。&lt;/p&gt;&lt;h2&gt;不同项目的组合策略&lt;/h2&gt;&lt;h3&gt;普通桌面程序&lt;/h3&gt;&lt;p&gt;先启用函数、字段、参数和类型重命名，再加字符串加密、数字混淆和流程混淆。确认功能正常后，再添加防调试、防ILSpy或加壳。&lt;/p&gt;&lt;h3&gt;供第三方调用的类库&lt;/h3&gt;&lt;p&gt;优先保护内部类型和实现。公开 API、反射入口、序列化模型等需谨慎重命名。字符串加密、流程混淆和函数体隐藏可用于保护不对外暴露的核心逻辑。&lt;/p&gt;&lt;h3&gt;包含重要算法的EXE&lt;/h3&gt;&lt;p&gt;可组合流程混淆、字符串隐藏、数字隐藏、函数调用混淆和函数体隐藏。完成兼容性测试后再考虑加壳、防篡改或原生化EXE。高强度选项应逐项开启并记录测试结果。&lt;/p&gt;&lt;h2&gt;推荐的启用和测试步骤&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;保留原始 DLL 或 EXE，准备覆盖核心功能的测试用例。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;先启用字段、函数、参数和类型重命名，验证程序能否启动。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;加入字符串加密、数字混淆和流程混淆，检查业务结果和性能。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;根据需要启用垃圾代码注入和反编译工具防护。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;最后测试函数体隐藏、加壳、原生化EXE等高强度选项。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;每增加一组功能都重新测试启动、登录、配置读写、网络请求等。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;若出现异常，可回到上一个可运行的组合逐个启用新选项。&lt;/p&gt;&lt;h2&gt;使用注意事项&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;保护强度越高不意味着越适合所有项目，应以稳定运行为前提。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;依赖反射、序列化、XAML 等时，重点测试重命名兼容性。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;防篡改、加壳和原生化EXE仅适用于 EXE。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;防虚拟机可能影响云桌面和虚拟化环境中的正常用户。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;处理后应在目标操作系统、架构和不同性能设备上验证。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;混淆用于提高逆向成本，不能替代权限控制、签名校验等服务端安全措施。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;总结&lt;/h2&gt;&lt;p&gt;恒盾C#混淆加密大师的各类选项各有针对性：基本保护用于应对调试和反编译工具，注入功能增加干扰，混淆功能隐藏代码流程和关键数据，重命名移除业务语义。&lt;/p&gt;&lt;p&gt;对于大多数项目，可从重命名、字符串加密、数字混淆和流程混淆开始，再根据程序类型增加防调试、工具防护、函数体隐藏、加壳或原生化EXE。逐步启用、逐步测试，才能在保护强度和兼容性之间取得平衡。&lt;/p&gt;</description><pubDate>Tue, 04 Aug 2026 19:56:34 +0800</pubDate></item><item><title>C#混淆随机种子有什么用？恒盾C#混淆加密大师使用教程</title><link>https://www.h5pack.com/post/csharp-obfuscator-random-seed-guide-zblog-h5pack.html</link><description>&lt;p&gt;在使用恒盾C#混淆加密大师处理 C# DLL 或 EXE 时，即使输入文件和保护选项相同，多次处理得到的结果也可能有所不同。这种随机性有助于避免不同构建始终呈现完全相同的混淆结果，但在问题排查、版本回归和自动化发布等场景中，有时也需要让结果更容易复现。&lt;/p&gt;&lt;p&gt;随机种子就是用于控制这种随机性的配置项。填写固定的随机种子后，对于同一个 EXE 或 DLL，在配置保持一致的情况下重复处理，可以获得更稳定、便于对比的混淆结果；留空时，软件会自动采用随机方式处理，让每次构建保持差异。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/08/1785763878840_b9f25423.png&quot; alt=&quot;恒盾C#混淆加密大师随机种子配置&quot;/&gt;&lt;/p&gt;&lt;h2&gt;随机种子有什么作用&lt;/h2&gt;&lt;p&gt;随机种子主要用于在“结果可复现”和“每次结果随机”之间进行选择。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;填写固定种子&lt;/strong&gt;：适合需要重复构建、对比结果、排查问题或保持发布流程一致的项目。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;留空不填&lt;/strong&gt;：软件会自动随机处理，适合希望不同构建产生不同混淆结果的日常发布场景。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;随机种子不会改变你选择了哪些保护功能，也不会替代字符串加密、流程混淆、重命名或其他保护选项。它只用于控制混淆过程中的随机结果是否便于再次复现。&lt;/p&gt;&lt;h2&gt;哪些场景适合设置固定种子&lt;/h2&gt;&lt;h3&gt;1. 排查混淆后的运行问题&lt;/h3&gt;&lt;p&gt;如果程序在混淆后出现异常，可以保留当前输入文件、混淆配置和随机种子，再次执行处理。固定种子能够减少重复测试时的结果差异，让开发者更容易判断问题是否与某项配置或程序改动有关。&lt;/p&gt;&lt;h3&gt;2. 进行版本回归测试&lt;/h3&gt;&lt;p&gt;在同一版本上多次验证启动、登录、授权、数据读写或其他核心功能时，使用固定种子可以让测试条件更加稳定。这样更适合比较不同保护选项启用前后的运行表现。&lt;/p&gt;&lt;h3&gt;3. 接入自动化构建和 CI/CD&lt;/h3&gt;&lt;p&gt;将混淆步骤加入构建脚本或持续集成流程后，可以为同一项目配置固定种子。开发机、构建机和发布流水线使用统一配置时，更容易复现某次构建并定位发布问题。&lt;/p&gt;&lt;h3&gt;4. 团队共享混淆配置&lt;/h3&gt;&lt;p&gt;多人维护同一个项目时，可以把随机种子与其他混淆选项一起保存到配置文件中。团队成员加载同一份配置后，可以减少因随机结果不同带来的沟通和验证成本。&lt;/p&gt;&lt;h3&gt;5. 保存可复现的发布记录&lt;/h3&gt;&lt;p&gt;对于重要版本，可以把当次使用的输入文件、混淆配置、软件版本和随机种子一起归档。后续需要复查或重新生成该版本时，会更容易恢复当时的处理条件。&lt;/p&gt;&lt;h2&gt;如何使用随机种子&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;打开恒盾C#混淆加密大师，选择需要处理的 DLL 或 EXE 文件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;根据项目需要勾选代码保护、代码混淆和重命名等选项。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在主界面下方找到“随机种子”输入框。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;输入便于识别的字母或数字，例如项目名称与版本号的组合。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;选择输出文件路径，然后点击“开始处理”。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;如果后续仍需复现本次结果，点击“保存配置”保留当前设置。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;随机种子支持字母和数字。建议使用团队容易识别、能够长期保存的内容，例如：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-text&quot;&gt;MyProduct150
Release202608
ClientA2026&lt;/pre&gt;&lt;p&gt;如果不需要复现处理结果，保持随机种子输入框为空即可。&lt;/p&gt;&lt;h2&gt;固定种子与留空随机应该怎么选&lt;/h2&gt;&lt;p&gt;如果当前工作重点是测试、排错、回归或自动化构建，建议设置固定种子。这样可以让多次处理更容易比较，也便于其他开发者复现相同条件。&lt;/p&gt;&lt;p&gt;如果当前工作重点是正式发布，并且希望不同发布批次的混淆结果保持差异，可以将随机种子留空，或者为每个版本使用不同的种子。&lt;/p&gt;&lt;p&gt;一种常见做法是：测试阶段固定使用项目级种子，正式发布时按版本设置不同种子。这样既方便日常验证，也能让不同版本之间保持差异。&lt;/p&gt;&lt;h2&gt;使用时需要注意什么&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;相同种子需要配合同一个输入文件和相同混淆配置，才便于复现结果。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;输入程序、保护选项或软件版本发生变化后，处理结果也可能随之变化。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;随机种子不是密码或授权密钥，不要在其中填写账号、密码等敏感信息。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;更换随机种子不等于提高保护强度，实际保护效果仍取决于启用的混淆和加密功能。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要复现正式版本时，应同时保存输入文件、配置文件、软件版本和随机种子。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;总结&lt;/h2&gt;&lt;p&gt;恒盾C#混淆加密大师的随机种子功能，可以让开发者根据实际需求选择更稳定、可复现的混淆结果，或保持每次处理的随机差异。&lt;/p&gt;&lt;p&gt;对于问题排查、回归测试、团队协作和 CI/CD，固定随机种子能够让构建条件更容易管理；对于希望不同发布版本保持差异的场景，则可以留空或按版本更换种子。合理使用这一配置，可以让 C# DLL、EXE 的混淆加密流程更加清晰，也更适合长期维护和自动化发布。&lt;/p&gt;</description><pubDate>Mon, 03 Aug 2026 21:31:17 +0800</pubDate></item><item><title>在.NET项目集成混淆加密功能：自动化保护DLL和EXE</title><link>https://www.h5pack.com/post/integrate-obfuscator-cli-into-dotnet-build.html</link><description>&lt;p&gt;为了保护C#程序, 在.NET项目交付DLL或EXE之前，通常需要先编译，再手动打开混淆工具、选择程序集、加载配置并导出结果。对于经常发布的项目，这套操作不仅重复，还容易漏选文件或使用错误配置。&lt;/p&gt;&lt;p&gt;更稳定的方式是把&lt;a href=&quot;https://csharpobf.leapever.com/&quot;&gt;恒盾C#混淆加密大师&lt;/a&gt;的CLI接入MSBuild：Release构建完成后自动获取当前项目的真实输出路径，调用CLI生成保护版本。由于Visual Studio、Rider、&lt;code&gt;dotnet build&lt;/code&gt;和多数CI平台最终都会调用MSBuild，因此只需在项目文件中维护一套规则。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/07/1785063359226_d964da73.png&quot; alt=&quot;C#混淆加密大师1.5.0截图&quot;/&gt;&lt;/p&gt;&lt;h2&gt;集成后的构建流程&lt;/h2&gt;&lt;p&gt;本文实现的流程如下：&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;正常编译.NET项目，不修改原始构建产物。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;仅在Release配置且已经配置CLI路径时执行混淆。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;将&lt;code&gt;.deps.json&lt;/code&gt;、&lt;code&gt;.runtimeconfig.json&lt;/code&gt;和依赖DLL复制到&lt;code&gt;protected&lt;/code&gt;目录。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;使用&lt;code&gt;--input&lt;/code&gt;和&lt;code&gt;--output&lt;/code&gt;覆盖配置文件中的路径，由CLI生成受保护的主程序集。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;CLI返回非零退出码或未生成目标文件时让构建失败，避免误发布未保护的程序。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;最终目录类似下面这样：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-text&quot;&gt;bin/Release/net8.0/
├─&amp;nbsp;DotNetObfuscationSample.dll&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原始构建产物
├─&amp;nbsp;DotNetObfuscationSample.deps.json
├─&amp;nbsp;DotNetObfuscationSample.runtimeconfig.json
└─&amp;nbsp;protected/
&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;DotNetObfuscationSample.dll&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;已混淆的主程序集
&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;DotNetObfuscationSample.deps.json
&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;DotNetObfuscationSample.runtimeconfig.json&lt;/pre&gt;&lt;p&gt;原始目录可继续用于调试和问题定位，发布时只取&lt;code&gt;protected&lt;/code&gt;目录即可。&lt;/p&gt;&lt;h2&gt;第一步：准备CLI和混淆配置&lt;/h2&gt;&lt;p&gt;安装恒盾C#混淆加密大师后，在安装目录中找到&lt;code&gt;CLI.exe&lt;/code&gt;。然后在图形界面中配置需要启用的保护功能，通过“文件 &amp;gt; 导出配置”得到&lt;code&gt;obfuscation.csop&lt;/code&gt;，并把它放在&lt;code&gt;.csproj&lt;/code&gt;同一目录。配置文件中的&lt;code&gt;ModulePath&lt;/code&gt;和&lt;code&gt;OutputPath&lt;/code&gt;可以保留示例值，因为构建时会通过CLI参数覆盖：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-jsonc&quot;&gt;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;ModulePath&amp;quot;:&amp;nbsp;&amp;quot;bin/Release/net8.0/MyApp.dll&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;OutputPath&amp;quot;:&amp;nbsp;&amp;quot;bin/Release/net8.0/protected/MyApp.dll&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;AntiILDasm&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;StringConfusor&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;IntConfusor&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;FieldRename&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;MethodRename&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;ParamRename&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;TypeRename&amp;quot;:&amp;nbsp;true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;RenameMode&amp;quot;:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Seed&amp;quot;:&amp;nbsp;&amp;quot;my-project-release&amp;quot;,
}&lt;/pre&gt;&lt;p&gt;实际使用时建议保留软件导出的完整配置，不要只复制上面的精简片段。可先启用少量保护选项，验证程序正常启动和主要功能后，再逐步增加保护强度。&lt;/p&gt;&lt;h2&gt;第二步：在项目文件中加入MSBuild目标&lt;/h2&gt;&lt;p&gt;打开需要保护的&lt;code&gt;.csproj&lt;/code&gt;，在&lt;code&gt;&amp;lt;/Project&amp;gt;&lt;/code&gt;之前加入下面的内容：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-xml&quot;&gt;&amp;lt;PropertyGroup&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;ObfuscatorCliPath&amp;nbsp;Condition=&amp;quot;&amp;#39;$(ObfuscatorCliPath)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;#39;&amp;quot;&amp;gt;$(OBFUSCATOR_CLI_PATH)&amp;lt;/ObfuscatorCliPath&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;RunObfuscator&amp;nbsp;Condition=&amp;quot;&amp;#39;$(RunObfuscator)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;#39;&amp;nbsp;and&amp;nbsp;&amp;#39;$(Configuration)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;Release&amp;#39;&amp;nbsp;and&amp;nbsp;&amp;#39;$(ObfuscatorCliPath)&amp;#39;&amp;nbsp;!=&amp;nbsp;&amp;#39;&amp;#39;&amp;quot;&amp;gt;true&amp;lt;/RunObfuscator&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;RunObfuscator&amp;nbsp;Condition=&amp;quot;&amp;#39;$(RunObfuscator)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;#39;&amp;quot;&amp;gt;false&amp;lt;/RunObfuscator&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;ObfuscatorConfigPath&amp;gt;$(MSBuildProjectDirectory)\obfuscation.csop&amp;lt;/ObfuscatorConfigPath&amp;gt;
&amp;lt;/PropertyGroup&amp;gt;

&amp;lt;Target&amp;nbsp;Name=&amp;quot;ObfuscateReleaseOutput&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AfterTargets=&amp;quot;Build&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Condition=&amp;quot;&amp;#39;$(Configuration)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;Release&amp;#39;&amp;nbsp;and&amp;nbsp;&amp;#39;$(RunObfuscator)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;true&amp;#39;&amp;quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;PropertyGroup&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ObfuscatedOutputDir&amp;nbsp;Condition=&amp;quot;&amp;#39;$(ObfuscatedOutputDir)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;#39;&amp;quot;&amp;gt;$(TargetDir)protected\&amp;lt;/ObfuscatedOutputDir&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ObfuscatedOutputPath&amp;nbsp;Condition=&amp;quot;&amp;#39;$(ObfuscatedOutputPath)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;#39;&amp;quot;&amp;gt;$(ObfuscatedOutputDir)$(TargetFileName)&amp;lt;/ObfuscatedOutputPath&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/PropertyGroup&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;lt;Error&amp;nbsp;Condition=&amp;quot;&amp;#39;$(ObfuscatorCliPath)&amp;#39;&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;#39;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text=&amp;quot;RunObfuscator=true,&amp;nbsp;but&amp;nbsp;ObfuscatorCliPath&amp;nbsp;or&amp;nbsp;OBFUSCATOR_CLI_PATH&amp;nbsp;is&amp;nbsp;not&amp;nbsp;configured.&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Error&amp;nbsp;Condition=&amp;quot;!Exists(&amp;#39;$(ObfuscatorCliPath)&amp;#39;)&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text=&amp;quot;Obfuscator&amp;nbsp;CLI&amp;nbsp;was&amp;nbsp;not&amp;nbsp;found:&amp;nbsp;$(ObfuscatorCliPath)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Error&amp;nbsp;Condition=&amp;quot;!Exists(&amp;#39;$(ObfuscatorConfigPath)&amp;#39;)&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text=&amp;quot;Obfuscator&amp;nbsp;config&amp;nbsp;was&amp;nbsp;not&amp;nbsp;found:&amp;nbsp;$(ObfuscatorConfigPath)&amp;quot;&amp;nbsp;/&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;lt;RemoveDir&amp;nbsp;Directories=&amp;quot;$(ObfuscatedOutputDir)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;MakeDir&amp;nbsp;Directories=&amp;quot;$(ObfuscatedOutputDir)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;ItemGroup&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ObfuscatorCompanionFile&amp;nbsp;Include=&amp;quot;$(TargetDir)**\*&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Exclude=&amp;quot;$(ObfuscatedOutputDir)**\*;$(TargetPath)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/ItemGroup&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Copy&amp;nbsp;SourceFiles=&amp;quot;@(ObfuscatorCompanionFile)&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DestinationFiles=&amp;quot;@(ObfuscatorCompanionFile-&amp;gt;&amp;#39;$(ObfuscatedOutputDir)%(RecursiveDir)%(Filename)%(Extension)&amp;#39;)&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SkipUnchangedFiles=&amp;quot;true&amp;quot;&amp;nbsp;/&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;lt;Message&amp;nbsp;Importance=&amp;quot;high&amp;quot;&amp;nbsp;Text=&amp;quot;Obfuscating&amp;nbsp;$(TargetPath)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;Command=&amp;quot;&amp;amp;quot;$(ObfuscatorCliPath)&amp;amp;quot;&amp;nbsp;obf&amp;nbsp;--config&amp;nbsp;&amp;amp;quot;$(ObfuscatorConfigPath)&amp;amp;quot;&amp;nbsp;--input&amp;nbsp;&amp;amp;quot;$(TargetPath)&amp;amp;quot;&amp;nbsp;--output&amp;nbsp;&amp;amp;quot;$(ObfuscatedOutputPath)&amp;amp;quot;&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Error&amp;nbsp;Condition=&amp;quot;!Exists(&amp;#39;$(ObfuscatedOutputPath)&amp;#39;)&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text=&amp;quot;Obfuscator&amp;nbsp;did&amp;nbsp;not&amp;nbsp;create&amp;nbsp;the&amp;nbsp;expected&amp;nbsp;output:&amp;nbsp;$(ObfuscatedOutputPath)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Message&amp;nbsp;Importance=&amp;quot;high&amp;quot;&amp;nbsp;Text=&amp;quot;Protected&amp;nbsp;output:&amp;nbsp;$(ObfuscatedOutputDir)&amp;quot;&amp;nbsp;/&amp;gt;
&amp;lt;/Target&amp;gt;&lt;/pre&gt;&lt;p&gt;这里使用的都是MSBuild内置属性，因此不需要硬编码项目名称或目标框架：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;$(MSBuildProjectDirectory)&lt;/code&gt;是当前项目目录。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;$(TargetPath)&lt;/code&gt;是本次构建产生的主程序集完整路径。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;$(TargetFileName)&lt;/code&gt;会自动适配不同项目名称。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;AfterTargets=&amp;quot;Build&amp;quot;&lt;/code&gt;确保只有编译成功后才执行CLI。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;Exec&lt;/code&gt;检查CLI退出码，随后的&lt;code&gt;Error&lt;/code&gt;还会确认目标文件确实已经生成。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;复制主程序集以外的完整输出内容，再由CLI生成受保护的主程序集，是为了保留程序运行需要的配置和依赖文件。不要只把混淆后的DLL单独交付。排除原始主程序集也能确保后续文件检查不会把未经保护的副本误判为成功结果。&lt;/p&gt;&lt;h2&gt;第三步：配置CLI路径&lt;/h2&gt;&lt;p&gt;不建议把个人电脑上的绝对安装路径写入&lt;code&gt;.csproj&lt;/code&gt;。可以使用环境变量，让不同开发机和CI环境使用各自的CLI位置。&lt;/p&gt;&lt;p&gt;在PowerShell中为当前终端设置：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;$env:OBFUSCATOR_CLI_PATH&amp;nbsp;=&amp;nbsp;&amp;#39;C:\Tools\CSharpObfuscator\CLI.exe&amp;#39;&lt;/pre&gt;&lt;p&gt;如需永久写入当前Windows用户的环境变量：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;[Environment]::SetEnvironmentVariable(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;OBFUSCATOR_CLI_PATH&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;C:\Tools\CSharpObfuscator\CLI.exe&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;User&amp;#39;
)&lt;/pre&gt;&lt;p&gt;永久设置后需要重新打开Visual Studio、Rider或终端。也可以在单次构建中直接传入路径：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;dotnet&amp;nbsp;build&amp;nbsp;-c&amp;nbsp;Release&amp;nbsp;-p:ObfuscatorCliPath=&amp;#39;C:\Tools\CSharpObfuscator\CLI.exe&amp;#39;&lt;/pre&gt;&lt;h2&gt;第四步：执行Release构建&lt;/h2&gt;&lt;p&gt;在命令行中执行：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;dotnet&amp;nbsp;build&amp;nbsp;-c&amp;nbsp;Release&lt;/pre&gt;&lt;p&gt;在Visual Studio中将解决方案配置切换为&lt;code&gt;Release&lt;/code&gt;后执行“生成解决方案”，或者在Rider中构建Release配置，都会触发同一个MSBuild目标。Debug构建默认不会执行混淆。&lt;/p&gt;&lt;p&gt;如需临时跳过混淆，可以显式关闭开关：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;dotnet&amp;nbsp;build&amp;nbsp;-c&amp;nbsp;Release&amp;nbsp;-p:RunObfuscator=false&lt;/pre&gt;&lt;p&gt;构建日志中出现下面两行，表示集成目标已执行：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-text&quot;&gt;Obfuscating&amp;nbsp;...\bin\Release\net8.0\MyApp.dll
Protected&amp;nbsp;output:&amp;nbsp;...\bin\Release\net8.0\protected\&lt;/pre&gt;&lt;h2&gt;在CI中使用&lt;/h2&gt;&lt;p&gt;CI使用的仍然是相同命令，只需提前安装并注册CLI，再通过环境变量或MSBuild属性传入路径：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;$env:OBFUSCATOR_CLI_PATH&amp;nbsp;=&amp;nbsp;&amp;quot;$env:OBFUSCATOR_HOME\CLI.exe&amp;quot;
dotnet&amp;nbsp;restore
dotnet&amp;nbsp;build&amp;nbsp;-c&amp;nbsp;Release&amp;nbsp;--no-restore&lt;/pre&gt;&lt;p&gt;建议把&lt;code&gt;protected&lt;/code&gt;目录作为发布制品，并在上传前增加一个文件存在性检查：&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-powershell&quot;&gt;$protectedFile&amp;nbsp;=&amp;nbsp;&amp;#39;.\bin\Release\net8.0\protected\MyApp.dll&amp;#39;
if&amp;nbsp;(-not&amp;nbsp;(Test-Path&amp;nbsp;$protectedFile))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;&amp;quot;未生成混淆后的程序集:&amp;nbsp;$protectedFile&amp;quot;
}&lt;/pre&gt;&lt;h2&gt;WPF、WinForms、&lt;a href=&quot;http://xn--ASP-8i4ek27bpw7b.NET&quot;&gt;类库和ASP.NET&lt;/a&gt; Core项目&lt;/h2&gt;&lt;p&gt;这套写法不依赖控制台项目：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;WPF和WinForms项目的&lt;code&gt;$(TargetPath)&lt;/code&gt;会指向其主程序集。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;类库项目可以直接保护生成的DLL。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://ASP.NET&quot;&gt;ASP.NET&lt;/a&gt; Core项目应在完整发布目录中保留依赖、配置文件和静态资源，仅替换需要保护的业务程序集。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;一个解决方案包含多个项目时，只在真正需要保护的项目中加入目标，或者把公共目标提取到单独的&lt;code&gt;.targets&lt;/code&gt;文件后按条件导入。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;使用反射、依赖注入扫描、JSON序列化、XAML绑定、插件加载或P/Invoke时，重命名可能影响运行。应通过忽略列表保留外部依赖的名称，并对启动、登录、核心业务、配置加载和自动更新等流程进行回归测试。&lt;/p&gt;&lt;h2&gt;&lt;code&gt;dotnet publish&lt;/code&gt;和单文件发布注意事项&lt;/h2&gt;&lt;p&gt;本文示例挂接在&lt;code&gt;Build&lt;/code&gt;目标之后，适合普通DLL、EXE构建。执行&lt;code&gt;dotnet publish&lt;/code&gt;时，发布过程还会在&lt;code&gt;publish&lt;/code&gt;目录重新整理文件，因此不要直接把未经检查的&lt;code&gt;publish&lt;/code&gt;目录当成混淆结果。&lt;/p&gt;&lt;p&gt;常规发布可先执行&lt;code&gt;dotnet publish -c Release&lt;/code&gt;，再用CLI的&lt;code&gt;--input&lt;/code&gt;和&lt;code&gt;--output&lt;/code&gt;处理发布目录中的主程序集。启用&lt;code&gt;PublishSingleFile&lt;/code&gt;时，应将发布得到的单文件EXE作为CLI输入，而不是构建阶段的DLL。建议为单文件项目单独建立发布后目标，并验证解包、混淆、重构后的程序能够在干净环境启动。&lt;/p&gt;&lt;h2&gt;完整示例代码&lt;/h2&gt;&lt;p&gt;可以访问GitHub获取完整项目代码: &lt;a href=&quot;https://github.com/leapever/csharp-obfuscator-cli-integration&quot;&gt;https://github.com/leapever/csharp-obfuscator-cli-integration&lt;/a&gt;&lt;/p&gt;</description><pubDate>Sun, 26 Jul 2026 18:55:59 +0800</pubDate></item><item><title>恒盾C#混淆加密大师1.5.0发布：EXE保护增强与.NET 10适配</title><link>https://www.h5pack.com/post/hengdun-csharp-obfuscator-1-5-0-release.html</link><description>&lt;p&gt;恒盾C#混淆加密大师 1.5.0 版本现已发布。本次更新聚焦于保护效果、运行兼容性和处理效率，增强了原生化EXE保护能力，适配最新的 .NET 10，并对多项常用混淆功能进行了集中优化。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/07/1784961802593_304a0670.png&quot; alt=&quot;C#混淆加密大师1.5.0截图&quot; width=&quot;961&quot; height=&quot;671&quot; style=&quot;width: 961px; height: 671px;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;下载最新版本&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://csharpobf.leapever.com&quot;&gt;点击进入下载页面&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;对于需要保护 C# DLL、EXE、WPF、WinForms、控制台程序以及其他 .NET 应用的开发者来说，1.5.0 是一次以稳定性和实用性为重点的升级。无论是单独启用某项保护，还是组合使用多项混淆功能，新版本都能更好地适应复杂项目和实际发布环境。&lt;/p&gt;&lt;h2&gt;1.5.0 版本重点更新&lt;/h2&gt;&lt;h3&gt;1. 增强原生化EXE保护效果&lt;/h3&gt;&lt;p&gt;1.5.0 进一步增强了原生化EXE的保护效果，可以提高程序被分析和还原的难度，为需要重点保护的 Windows EXE 程序提供更强的安全保障。&lt;/p&gt;&lt;p&gt;这项更新适合用于商业桌面软件、企业内部工具、授权客户端以及包含重要业务逻辑的应用程序。通过升级后的原生化EXE功能，开发者可以在保持程序正常交付和运行的同时，进一步加强对核心代码和软件成果的保护。&lt;/p&gt;&lt;h3&gt;2. 更新混淆内核，适配最新.NET 10&lt;/h3&gt;&lt;p&gt;随着 .NET 平台持续更新，混淆工具也需要及时适配新的程序格式和开发环境。1.5.0 更新了混淆内核，现已适配最新的 .NET 10，为使用新版本 .NET 构建项目的开发者提供支持。&lt;/p&gt;&lt;p&gt;对于计划升级到 .NET 10，或已经开始使用 .NET 10 开发和发布程序的团队，新版本可以更顺畅地接入现有保护流程。同时，原有 .NET 项目仍可继续使用，便于开发者在不同版本的项目之间保持统一的混淆加密方案。&lt;/p&gt;&lt;h3&gt;3. 提升防篡改功能的兼容性&lt;/h3&gt;&lt;p&gt;防篡改功能可以帮助开发者降低程序文件被修改后继续运行的风险。1.5.0 提升了该功能的兼容性，使其在更多EXE程序以及多种保护功能组合使用时表现得更加稳定。&lt;/p&gt;&lt;p&gt;对于同时启用函数体隐藏、资源文件混淆或其他保护选项的项目，这项改进可以减少功能之间相互影响的情况，让开发者更方便地根据项目需求组合不同的保护能力。&lt;/p&gt;&lt;h3&gt;4. 提升资源文件混淆的兼容性&lt;/h3&gt;&lt;p&gt;.NET 程序经常会包含界面资源、文本资源、配置资源以及其他随程序集发布的内容。1.5.0 提升了资源文件混淆的兼容性，使资源保护功能能够适应更多类型的项目。&lt;/p&gt;&lt;p&gt;这项更新对于资源使用较多的 WPF、WinForms 和桌面应用尤其有价值。开发者可以继续保护程序中的资源内容，同时降低混淆后出现资源读取异常或程序运行异常的概率。&lt;/p&gt;&lt;h3&gt;5. 提升隐藏函数体的兼容性&lt;/h3&gt;&lt;p&gt;隐藏函数体是保护关键业务逻辑的重要功能之一。1.5.0 对该功能进行了兼容性优化，使其能够更稳定地应用于包含复杂调用关系和多种程序结构的项目。&lt;/p&gt;&lt;p&gt;如果程序中包含授权验证、业务规则、数据处理或其他不希望被直接查看的关键逻辑，可以使用隐藏函数体功能提高分析难度。新版本让这项保护能力在实际项目中更易于使用，也更适合与其他混淆选项配合启用。&lt;/p&gt;&lt;h3&gt;6. 提升隐藏字符串和数字的兼容性&lt;/h3&gt;&lt;p&gt;程序中的字符串和数字常常包含接口地址、业务参数、授权信息、状态标识或其他敏感内容。1.5.0 提升了隐藏字符串和数字功能的兼容性，使其可以覆盖更多使用场景，并改善与其他保护功能同时启用时的稳定性。&lt;/p&gt;&lt;p&gt;对于敏感常量较多，或希望减少程序静态信息暴露的项目，这项更新可以提供更完整的保护体验。开发者无需改变原有业务代码，即可继续通过统一配置保护相关内容。&lt;/p&gt;&lt;h3&gt;7. 优化核心混淆速度&lt;/h3&gt;&lt;p&gt;除了保护效果和兼容性提升之外，1.5.0 还优化了核心混淆速度。对于程序集较多、项目体积较大或需要频繁执行混淆的开发者，新版本可以缩短等待时间，提高日常构建和发布效率。&lt;/p&gt;&lt;p&gt;这项优化也更适合自动化构建、持续集成和批量处理场景。团队可以将混淆步骤继续保留在现有发布流程中，同时获得更流畅的处理体验。&lt;/p&gt;&lt;h2&gt;多项保护功能配合使用更加稳定&lt;/h2&gt;&lt;p&gt;真实项目通常不会只使用单一保护功能，而是会根据程序特点组合启用原生化EXE、防篡改、资源文件混淆、隐藏函数体以及隐藏字符串和数字等功能。&lt;/p&gt;&lt;p&gt;1.5.0 对这些常用能力进行了整体兼容性提升，重点改善多项功能同时启用时的稳定性。对于结构复杂、资源较多或保护要求较高的项目，新版本能够减少反复调整配置的成本，让混淆加密流程更容易融入日常开发和发布工作。&lt;/p&gt;&lt;h2&gt;这次更新适合哪些用户&lt;/h2&gt;&lt;p&gt;如果你有以下需求，建议升级到 1.5.0：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;需要增强 Windows EXE 程序的原生化保护效果&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;正在使用或准备升级到 .NET 10&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要对 C# DLL 或 EXE 进行混淆加密&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要组合使用防篡改、资源文件混淆和函数体隐藏等功能&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要保护程序中的字符串、数字和关键业务逻辑&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要提升大型项目或自动化发布流程中的混淆处理效率&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;总结&lt;/h2&gt;&lt;p&gt;恒盾C#混淆加密大师 1.5.0 是一次围绕保护强度、平台适配、功能兼容性和处理效率展开的重要更新。新版本不仅增强了原生化EXE保护效果并适配最新的 .NET 10，还集中提升了防篡改、资源文件混淆、隐藏函数体、隐藏字符串和数字等核心功能的稳定性。&lt;/p&gt;&lt;p&gt;对于需要在真实项目中长期使用 C# 混淆、DLL加密和EXE保护的开发者来说，1.5.0 能够提供更完整、更稳定且更高效的代码保护体验。&lt;/p&gt;</description><pubDate>Sat, 25 Jul 2026 14:43:22 +0800</pubDate></item><item><title>EXE加密原生内核使用指南：无需系统环境即可运行</title><link>https://www.h5pack.com/post/exe-encryptor-native-kernel-guide.html</link><description>&lt;h1&gt;EXE加密原生内核使用指南：无需系统环境即可运行&lt;/h1&gt;&lt;p&gt;使用EXE一机一码打包加密大师时，软件默认使用普通内核进行打包，可以满足绝大多数电脑的运行需求。但少数电脑由于系统版本较旧、经过精简、处于内网隔离环境，或安装了较为严格的安全防护软件，打包后的程序可能出现双击没有反应、启动后立即关闭或运行异常的情况。遇到这类问题时，可以尝试切换为&lt;strong&gt;原生内核&lt;/strong&gt;重新打包。如果你不了解EXE一机一码打包加密大师, 可以访问官网查看具体介绍和说明.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://exeenc.leapever.com/&quot;&gt;点击进入EXE一机一码打包加密大师官网&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;什么是原生内核&lt;/h2&gt;&lt;p&gt;在&lt;strong&gt;快速打包&lt;/strong&gt;页面的设置区域中，“加密壳”一项提供两种内核可选：&lt;strong&gt;普通内核&lt;/strong&gt;和&lt;strong&gt;原生内核&lt;/strong&gt;。普通内核是默认选项，需要一定的系统环境支持，适合绝大多数Windows电脑；原生内核则不依赖额外的系统环境，程序可以直接运行，通用性更好，尤其适合运行环境比较特殊的电脑。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/07/1783858463235_f04918ab.png&quot; alt=&quot;原生内核&quot;/&gt;&lt;/p&gt;&lt;p&gt;两种内核只是加密壳的运行载体不同，不会影响你选择的一机一码、静态密码或网络验证等授权方式，也不会改变激活码的计算方式。切换内核后原有的授权设置可以继续沿用，如果已经生成过激活码，建议切换内核后重新打包并在目标电脑上测试。&lt;/p&gt;&lt;h2&gt;适用场景&lt;/h2&gt;&lt;p&gt;以下情况可以优先考虑切换到原生内核重新打包：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;打包后的程序在部分电脑上双击没有反应、启动后一闪而过，或者提示缺少组件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;目标电脑系统版本较旧（例如仍在使用Windows 7）、是精简版系统镜像，或者是刚安装不久、组件不全的系统。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;软件需要部署在完全离线、无法连接网络更新系统组件的电脑上。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;目标电脑处于企业内网、政府机关等环境，安装策略较为严格，无法自由安装额外的系统组件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;已经尝试过兼容模式，问题依然存在，希望进一步提高打包程序的通用性。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/07/1783858463849_7dfcf2f0.png&quot; alt=&quot;打包问题&quot;/&gt;&lt;/p&gt;&lt;p&gt;如果打包后的程序在普通内核下已经可以正常运行，无需切换，保持默认设置即可。&lt;/p&gt;&lt;h2&gt;使用方法&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;打开EXE一机一码打包加密大师，进入&lt;strong&gt;快速打包&lt;/strong&gt;页面。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;按照正常流程选择需要打包的EXE文件，设置软件名称、加密模式等选项。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在设置区域的“加密壳”一项中，选择&lt;strong&gt;原生内核&lt;/strong&gt;（默认使用的是普通内核）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;点击“打包”按钮生成加密程序。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;将生成的程序复制到目标电脑上测试运行效果，确认可以正常启动和使用。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;使用建议&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;建议先使用默认的普通内核打包测试，只有在目标电脑上出现无法启动、运行异常等问题时，再切换为原生内核重新打包。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;原生内核和兼容模式可以配合使用：如果单独切换原生内核后问题仍未解决，可以同时勾选兼容模式一起测试。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;每次调整内核或其他打包设置后，建议在实际使用的电脑上重新测试一遍，确认无误后再正式对外分发。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description><pubDate>Sun, 12 Jul 2026 20:14:23 +0800</pubDate></item><item><title>EXE一机一码加密后无法运行？兼容模式使用指南</title><link>https://www.h5pack.com/post/exe-encryptor-compatible-mode-guide.html</link><description>&lt;h1&gt;EXE一机一码加密后无法运行？兼容模式使用指南&lt;/h1&gt;&lt;p&gt;使用EXE一机一码打包加密大师后，如果原始EXE可以正常运行，但打包生成的程序出现点击后没有反应、启动后立即关闭、启动时报错或部分功能异常。此类情况通常与原软件自身的运行方式有关，并不一定是加密方式或授权设置有问题, 本文主要介绍如何解决一些常见的兼容性问题。如果你不了解EXE一机一码打包加密大师, 可以访问官网查看具体介绍和说明.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://exeenc.leapever.com/&quot;&gt;点击进入EXE一机一码打包加密大师官网&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;解决方案详解&lt;/h2&gt;&lt;p&gt;在普通模式打包时，软件会使用常规方案进行打包，进行高强度加密，适合绝大多数EXE程序。如果打包后的程序可以正常启动和使用，保持默认设置即可。&lt;/p&gt;&lt;p&gt;而部分EXE程序带有自身完整性校验、特殊的启动流程，或者需要与其他程序文件紧密配合；一些使用较老或较少见开发环境制作的软件，也可能对打包后的运行方式比较敏感。遇到这些情况时，开启&lt;strong&gt;兼容模式&lt;/strong&gt;通常可以提高打包后程序的适应性，改善无法启动、意外退出或功能运行异常等问题。&lt;/p&gt;&lt;p&gt;使用时，在&lt;strong&gt;快速打包&lt;/strong&gt;页面的设置区域找到&lt;strong&gt;兼容模式&lt;/strong&gt;，勾选“使用兼容加密模式”，然后重新打包并测试生成的程序。开启兼容模式不会改变您选择的一机一码、静态密码或网络验证方式，也不需要修改原始EXE。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/07/1783773173102_e2c3dc59.png&quot; alt=&quot;兼容模式按钮&quot;/&gt;&lt;/p&gt;&lt;p&gt;建议先使用默认模式打包；如果默认模式运行正常，就继续使用默认方案。如果默认模式生成的程序无法正常运行，再开启兼容模式重新打包，并在实际使用的电脑上测试。兼容模式主要用于解决原始EXE本身可以运行、加密后才出现异常的情况；如果原始EXE也无法运行，则需要先检查原程序自身的运行条件。&lt;/p&gt;</description><pubDate>Sat, 11 Jul 2026 20:32:53 +0800</pubDate></item><item><title>多实例共享进程：让HTML打包的EXE更快多开并共享登录</title><link>https://www.h5pack.com/post/html2exe-multi-instance-shared-process-zblog-h5pack.html</link><description>&lt;p&gt;在一些网页应用打包成EXE后，用户可能会习惯同时打开多个窗口。例如后台系统需要一边查看订单列表，一边打开客户详情；运营工具需要同时对比多个页面；或者同一个网站需要频繁打开多个独立窗口。&lt;/p&gt;&lt;p&gt;如果每次双击EXE都完整启动一个新的程序实例，第二个、第三个窗口有时会明显变慢，甚至出现短暂白屏。&lt;strong&gt;多实例共享进程&lt;/strong&gt;就是为这类场景准备的功能：在同一个EXE已经运行时，再次打开它，可以更快显示新窗口，并共享同一套登录状态。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://api.leapever.com/packerv2/download&quot;&gt;立即下载最新版本&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://leapever.com/intro/html2exe/&quot;&gt;HTML打包EXE工具官网&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;多实例共享进程是什么？&lt;/h2&gt;&lt;p&gt;简单来说，它可以让同一个EXE在多次打开时表现得更像一个完整的多窗口应用：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;第一次打开 EXE：正常启动程序&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;程序已经运行时再次打开同一个 EXE：快速打开一个新窗口&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;新窗口与已有窗口共享登录状态、Cookie、本地存储等数据&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;用户可以同时使用多个窗口，而不必等待每次都完整启动&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;注意：这不是“单例模式”。单例模式的目标是&lt;strong&gt;只允许一个窗口存在&lt;/strong&gt;，再次打开时只会回到已有窗口；多实例共享进程的目标是&lt;strong&gt;允许多个窗口存在&lt;/strong&gt;，只是让后续窗口打开得更快、更稳定。&lt;/p&gt;&lt;h2&gt;这个功能能解决什么问题？&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;后续窗口打开更快&lt;/strong&gt;：对于内容较重的网站，完整启动新实例可能需要较长时间。开启后，在已有窗口运行下再次打开EXE，通常能更快显示新窗口。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;减少白屏等待&lt;/strong&gt;：第二个窗口常出现的几秒钟白屏，通过此功能可显著缩短。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;多窗口共享登录状态&lt;/strong&gt;：用户在第一个窗口登录后，再开新窗口无需重新登录，Cookie和本地数据保持一致。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;更适合多窗口办公&lt;/strong&gt;：例如一个窗口查看列表，另一个查看详情，并排对照处理。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;什么时候推荐开启？&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;用户经常重复双击同一个EXE打开多个窗口&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要同时查看多个页面或多个业务对象&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;第二个窗口打开时有明显白屏或等待&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;应用需要保持统一登录状态&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;应用是后台系统、业务系统、管理系统等&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;什么时候不建议开启？&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;希望每次EXE都是完全独立的数据环境&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;需要同时登录多个不同账号进行测试&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;已开启隐身模式或禁用缓存&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;目标为“只能打开一个窗口”，请使用单例模式&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;如何开启多实例共享进程&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;打开 HTML打包EXE 工具&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;进入&lt;strong&gt;高级设置&lt;/strong&gt;页面&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;勾选&lt;strong&gt;多实例共享进程&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;正常点击&lt;strong&gt;打包&lt;/strong&gt;生成 EXE&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;img src=&quot;https://www.h5pack.com/zb_users/upload/2026/07/1783429979681_5498960f.png&quot; alt=&quot;多实例共享进程&quot;/&gt;&lt;/p&gt;&lt;h2&gt;与单例模式的区别&lt;/h2&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;功能&lt;/th&gt;&lt;th&gt;单例模式&lt;/th&gt;&lt;th&gt;多实例共享进程&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;是否允许多个窗口&lt;/td&gt;&lt;td&gt;不允许&lt;/td&gt;&lt;td&gt;允许&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;再次双击EXE&lt;/td&gt;&lt;td&gt;回到已有窗口&lt;/td&gt;&lt;td&gt;打开新窗口&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;是否共享登录状态&lt;/td&gt;&lt;td&gt;共享&lt;/td&gt;&lt;td&gt;共享&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;适合场景&lt;/td&gt;&lt;td&gt;单窗口应用&lt;/td&gt;&lt;td&gt;多页面业务系统&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h2&gt;常见问题&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;开启后是否每个窗口都能共享登录状态？&lt;/strong&gt;通常可以，只要网站使用常见的Cookie、本地存储方式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;可以用来同时登录多个账号吗？&lt;/strong&gt;不推荐。如需多账号登录，请使用默认多实例方式或不同软件ID打包。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;为什么需要填写软件ID？&lt;/strong&gt;用于区分不同的打包应用，避免数据影响。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;和隐身模式/禁用缓存能一起用吗？&lt;/strong&gt;不建议，目标相反。&lt;/p&gt;&lt;h2&gt;总结&lt;/h2&gt;&lt;p&gt;多实例共享进程适合需要频繁打开多个同一EXE窗口的应用，让后续窗口打开更快，减少白屏，共享登录状态。建议在打包时根据需求启用。&lt;/p&gt;&lt;h2&gt;相关阅读&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://leapever.com/tutorial/html2exe-window-mode-guide&quot;&gt;HTML打包EXE工具四种弹窗方式图文详解&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://leapever.com/tutorial/html2exe-tab-mode-guide&quot;&gt;HTML打包EXE工具标签页模式详解&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://leapever.com/tutorial/html-pack-exe-function-introduction&quot;&gt;HTML打包EXE工具功能介绍&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description><pubDate>Tue, 07 Jul 2026 21:12:57 +0800</pubDate></item></channel></rss>