no message

This commit is contained in:
yinjun.chen1
2026-09-14 15:38:07 +08:00
parent f22b45ba5b
commit 1fd3cfbd44
7 changed files with 1839 additions and 216 deletions
+81 -81
View File
@@ -7,123 +7,123 @@
<title>Auto Login Manager</title>
</head>
<body>
<!-- 锁定/设置口令覆盖层 -->
<!-- 锁定/设置本机密码覆盖层 -->
<div id="lockScreen" class="lock-screen">
<div class="lock-card">
<img src="icons/icon128.png" alt="logo" class="lock-logo">
<h2 id="lockTitle">设置本机密码</h2>
<p id="lockHint" class="lock-hint">本机密码用于加密存储所有配置,忘记将无法恢复</p>
<h2 id="lockTitle" data-i18n="lockSetupTitle">设置本机密码</h2>
<p id="lockHint" class="lock-hint" data-i18n="lockSetupHint">本机密码用于加密存储所有配置,忘记将无法恢复</p>
<div class="form-group">
<input type="password" id="lockPassword" placeholder="请输入本机密码" autocomplete="off">
<input type="password" id="lockPassword" data-i18n-placeholder="lockPasswordPlaceholder" placeholder="请输入本机密码" autocomplete="off">
</div>
<div class="form-group" id="lockConfirmGroup">
<label for="lockPasswordConfirm">确认本机密码</label>
<input type="password" id="lockPasswordConfirm" placeholder="再次输入本机密码" autocomplete="off">
<label for="lockPasswordConfirm" data-i18n="lockPasswordConfirmLabel">确认本机密码</label>
<input type="password" id="lockPasswordConfirm" data-i18n-placeholder="lockPasswordConfirmPlaceholder" placeholder="再次输入本机密码" autocomplete="off">
</div>
<div class="lock-warn" id="lockWarn"></div>
<button type="button" id="lockSubmitBtn" class="btn-primary lock-submit">设置本机密码</button>
<p class="lock-footnote">本机密码仅用于本地加密,不会上传到任何服务器</p>
<button type="button" id="lockSubmitBtn" class="btn-primary lock-submit" data-i18n="lockSetupBtn">设置本机密码并进入</button>
<p class="lock-footnote" data-i18n="lockFootnote">本机密码仅用于本地加密,不会上传到任何服务器</p>
</div>
</div>
<div class="container" id="mainContainer" style="display:none;">
<header>
<button type="button" id="lockBtn" class="btn-lock" title="锁定(清除内存中的明文)">🔒</button>
<button type="button" id="lockBtn" class="btn-lock" data-i18n-title="lockBtnTitle" title="锁定(清除内存中的明文)">🔒</button>
<div class="header-title">
<img src="icons/icon128.png" alt="logo" class="header-logo">
<h1>Auto Login Manager</h1>
<h1 data-i18n="appTitle">Auto Login Manager</h1>
</div>
<div class="env-bar">
<label class="env-label">当前环境</label>
<label class="env-label" data-i18n="currentEnvLabel">当前环境</label>
<div class="env-controls">
<select id="envSelect" class="env-select"></select>
<button type="button" id="envManageBtn" class="btn-env" title="管理环境(新建 / 重命名 / 删除)">⚙</button>
<button type="button" id="envManageBtn" class="btn-env" data-i18n-title="envManageBtnTitle" title="管理环境(新建 / 重命名 / 删除)">⚙</button>
</div>
</div>
</header>
<section class="add-section" id="addSection">
<h2>添加域名配置</h2>
<h2 data-i18n="addConfigTitle">添加域名配置</h2>
<div class="form-group">
<label for="domain">域名 / URL 匹配规则</label>
<label for="domain" data-i18n="domainLabel">域名 / URL 匹配规则</label>
<div class="domain-wrapper">
<input type="text" id="domain" placeholder="example.com 或 *.example.com 或 site.com/admin/*">
<button type="button" id="fillDomain" class="btn-fill-domain" title="填入当前标签页域名">填入当前域名</button>
<input type="text" id="domain" data-i18n-placeholder="domainPlaceholder" placeholder="example.com 或 *.example.com 或 site.com/admin/*">
<button type="button" id="fillDomain" class="btn-fill-domain" data-i18n="fillDomainBtn" data-i18n-title="fillDomainBtnTitle" title="填入当前标签页域名">填入当前域名</button>
</div>
<small>支持通配符 *。带 / 时按 hostname+path 匹配,如 oa.com/login/*;不带 / 时只匹配域名</small>
<small data-i18n="domainHelp">支持通配符 *。带 / 时按 hostname+path 匹配,如 oa.com/login/*;不带 / 时只匹配域名</small>
</div>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" placeholder="输入用户名">
<label for="username" data-i18n="usernameLabel">用户名</label>
<input type="text" id="username" data-i18n-placeholder="usernamePlaceholder" placeholder="输入用户名">
</div>
<div class="form-group">
<label for="password">密码</label>
<label for="password" data-i18n="passwordLabel">密码</label>
<div class="password-wrapper">
<input type="password" id="password" placeholder="输入密码">
<button class="toggle-pwd eye-open" type="button" data-target="password" aria-label="切换密码显示">👁</button>
<input type="password" id="password" data-i18n-placeholder="passwordPlaceholder" placeholder="输入密码">
<button class="toggle-pwd eye-open" type="button" data-target="password" data-i18n-aria="togglePwdAria" aria-label="切换密码显示">👁</button>
</div>
</div>
<div class="form-group">
<label for="alias">别名(可选)</label>
<input type="text" id="alias" placeholder="例如: 公司OA、GitLab、邮箱">
<small>方便识别该配置,留空则显示域名</small>
<label for="alias" data-i18n="aliasLabel">别名(可选)</label>
<input type="text" id="alias" data-i18n-placeholder="aliasPlaceholder" placeholder="例如: 公司OA、GitLab、邮箱">
<small data-i18n="aliasHelp">方便识别该配置,留空则显示域名</small>
</div>
<details class="advanced-options">
<summary>高级选项(选填,默认即可)</summary>
<summary data-i18n="advancedOptionsSummary">高级选项(选填,默认即可)</summary>
<div class="advanced-options-body">
<div class="form-group">
<label for="autoSubmit">自动提交登录</label>
<label for="autoSubmit" data-i18n="autoSubmitLabel">自动提交登录</label>
<select id="autoSubmit">
<option value="true">是 - 自动点击登录按钮</option>
<option value="false">否 - 仅填充不提交</option>
<option value="true" data-i18n="autoSubmitYes">是 - 自动点击登录按钮</option>
<option value="false" data-i18n="autoSubmitNo">否 - 仅填充不提交</option>
</select>
</div>
<div class="form-group">
<label for="enabled">启用 / 禁用</label>
<label for="enabled" data-i18n="enabledLabel">启用 / 禁用</label>
<label class="toggle-switch">
<input type="checkbox" id="enabled" checked>
<span class="toggle-slider"></span>
</label>
<small>禁用后该条配置将不会生效</small>
<small data-i18n="enabledHelp">禁用后该条配置将不会生效</small>
</div>
<div class="form-group">
<label for="delayMs">填充延迟(毫秒,可选)</label>
<input type="number" id="delayMs" min="0" max="10000" step="100" placeholder="留空=默认 300ms,可填 500-2000 用于 SPA 页面">
<small>某些页面(Ant Design、ASP.NET)需 JS 初始化,立即填充会失效</small>
<label for="delayMs" data-i18n="delayMsLabel">填充延迟(毫秒,可选)</label>
<input type="number" id="delayMs" min="0" max="10000" step="100" data-i18n-placeholder="delayMsPlaceholder" placeholder="留空=默认 300ms,可填 500-2000 用于 SPA 页面">
<small data-i18n="delayMsHelp">某些页面(Ant Design、ASP.NET)需 JS 初始化,立即填充会失效</small>
</div>
<div class="selector-tutorial">
<p class="help-tip">下面三项通常<strong>留空即可</strong>,插件会自动找到登录框。只有当自动填充失败、或填错位置时才需要填。</p>
<p class="help-step">1. 在登录页面按 <kbd>F12</kbd> 打开开发者工具,切到"Elements(元素)"标签</p>
<p class="help-step">2. 点开发者工具左上角的 <span class="icon-arrow">箭头图标</span>,再去点页面上的输入框/按钮</p>
<p class="help-step">3. 工具会跳到对应的 HTML 行,在 <code>&lt;input&gt;</code> 或 <code>&lt;button&gt;</code> 标签上看 <code>id</code>、<code>name</code>、<code>class</code>、<code>type</code> 属性</p>
<p class="help-step">4. 按 <span class="rule-tag">#id</span>、<span class="rule-tag">.class</span>、<span class="rule-tag">[name=xxx]</span>、<span class="rule-tag">tag[属性=值]</span> 规则组合填写即可</p>
<p class="help-tip" data-i18n="selectorHelpTip">下面三项通常<strong>留空即可</strong>,插件会自动找到登录框。只有当自动填充失败、或填错位置时才需要填。</p>
<p class="help-step" data-i18n="selectorHelpStep1">1. 在登录页面按 <kbd>F12</kbd> 打开开发者工具,切到"Elements(元素)"标签</p>
<p class="help-step" data-i18n="selectorHelpStep2">2. 点开发者工具左上角的 <span class="icon-arrow">箭头图标</span>,再去点页面上的输入框/按钮</p>
<p class="help-step" data-i18n="selectorHelpStep3">3. 工具会跳到对应的 HTML 行,在 &lt;input&gt; 或 &lt;button&gt; 标签上看 id、name、class、type 属性</p>
<p class="help-step" data-i18n="selectorHelpStep4">4. 按 #id、.class、[name=xxx]、tag[属性=值] 规则组合填写即可</p>
</div>
<div class="form-group">
<label>用户名输入框位置</label>
<input type="text" id="usernameSelector" placeholder="留空=自动查找,如 #username 或 input[name=account]">
<small>留空即可。填错会导致用户名填不进框。</small>
<label data-i18n="usernameSelectorLabel">用户名输入框位置</label>
<input type="text" id="usernameSelector" data-i18n-placeholder="usernameSelectorPlaceholder" placeholder="留空=自动查找,如 #username 或 input[name=account]">
<small data-i18n="usernameSelectorHelp">留空即可。填错会导致用户名填不进框。</small>
</div>
<div class="form-group">
<label>密码输入框位置</label>
<input type="text" id="passwordSelector" placeholder="留空=自动查找,如 #password 或 input[type=password]">
<small>留空即可。填错会导致密码填不进框。</small>
<label data-i18n="passwordSelectorLabel">密码输入框位置</label>
<input type="text" id="passwordSelector" data-i18n-placeholder="passwordSelectorPlaceholder" placeholder="留空=自动查找,如 #password 或 input[type=password]">
<small data-i18n="passwordSelectorHelp">留空即可。填错会导致密码填不进框。</small>
</div>
<div class="form-group">
<label>登录按钮位置</label>
<input type="text" id="submitSelector" placeholder="留空=自动查找,如 #loginBtn 或 button[type=submit]">
<small>留空即可。填错会导致不会自动点击登录。</small>
<label data-i18n="submitSelectorLabel">登录按钮位置</label>
<input type="text" id="submitSelector" data-i18n-placeholder="submitSelectorPlaceholder" placeholder="留空=自动查找,如 #loginBtn 或 button[type=submit]">
<small data-i18n="submitSelectorHelp">留空即可。填错会导致不会自动点击登录。</small>
</div>
</div>
</details>
<button id="addBtn" class="btn-primary">添加配置</button>
<button id="addBtn" class="btn-primary" data-i18n="addConfigBtn">添加配置</button>
</section>
<section class="list-section" id="listSection">
<div class="list-header">
<h2>已配置域名</h2>
<h2 data-i18n="configuredDomainsTitle">已配置域名</h2>
<div class="list-actions">
<button type="button" id="exportBtn" class="btn-io">导出</button>
<button type="button" id="importBtn" class="btn-io">导入</button>
<button type="button" id="exportBtn" class="btn-io" data-i18n="exportBtn">导出</button>
<button type="button" id="importBtn" class="btn-io" data-i18n="importBtn">导入</button>
<input type="file" id="importFile" accept="application/json,.json" hidden>
</div>
</div>
@@ -132,90 +132,90 @@
</section>
<section class="current-section">
<button id="fillCurrent" class="btn-secondary">在当前页面填充</button>
<button id="fillCurrent" class="btn-secondary" data-i18n="fillCurrentBtn">在当前页面填充</button>
</section>
<footer class="footer">
<p class="powered-by">power by chenxuan</p>
<p class="powered-by" data-i18n="poweredBy">power by chenxuan</p>
</footer>
</div>
<div id="toast" class="toast"></div>
<!-- 环境管理对话框:列出所有环境,每行带编辑/删除,底部新建按钮 -->
<!-- 环境管理对话框 -->
<div id="envManageModal" class="modal">
<div class="modal-content">
<h3>环境管理</h3>
<h3 data-i18n="envManageTitle">环境管理</h3>
<div id="envManageList" class="env-manage-list"></div>
<div class="modal-warn" id="envManageWarn" style="display:none;"></div>
<div class="modal-actions">
<button type="button" id="envManageClose" class="btn-edit">关闭</button>
<button type="button" id="envManageAdd" class="btn-primary">+ 新建环境</button>
<button type="button" id="envManageClose" class="btn-edit" data-i18n="closeBtn">关闭</button>
<button type="button" id="envManageAdd" class="btn-primary" data-i18n="createEnvBtn">+ 新建环境</button>
</div>
</div>
</div>
<div id="envModal" class="modal">
<div class="modal-content">
<h3 id="envModalTitle">新建环境</h3>
<h3 id="envModalTitle" data-i18n="envCreateTitle">新建环境</h3>
<div class="form-group">
<label for="envNameInput">环境名称</label>
<input type="text" id="envNameInput" placeholder="例如: 个人 / 测试 / 生产 / 客户A">
<label for="envNameInput" data-i18n="envNameLabel">环境名称</label>
<input type="text" id="envNameInput" data-i18n-placeholder="envNamePlaceholder" placeholder="例如: 个人 / 测试 / 生产 / 客户A">
</div>
<div class="preset-env-tags" id="presetEnvTags">
<span class="preset-tag" data-name="个人">个人</span>
<span class="preset-tag" data-name="测试">测试</span>
<span class="preset-tag" data-name="生产">生产</span>
<span class="preset-tag" data-name="开发">开发</span>
<span class="preset-tag" data-name="预发">预发</span>
<span class="preset-tag" data-name="个人" data-i18n="presetPersonal">个人</span>
<span class="preset-tag" data-name="测试" data-i18n="presetTest">测试</span>
<span class="preset-tag" data-name="生产" data-i18n="presetProd">生产</span>
<span class="preset-tag" data-name="开发" data-i18n="presetDev">开发</span>
<span class="preset-tag" data-name="预发" data-i18n="presetStaging">预发</span>
</div>
<div class="modal-warn" id="envModalWarn" style="display:none;"></div>
<div class="modal-actions">
<button type="button" id="envModalCancel" class="btn-edit">取消</button>
<button type="button" id="envModalConfirm" class="btn-primary">确认</button>
<button type="button" id="envModalCancel" class="btn-edit" data-i18n="cancelBtn">取消</button>
<button type="button" id="envModalConfirm" class="btn-primary" data-i18n="confirmBtn">确认</button>
</div>
</div>
</div>
<div id="pwdModal" class="modal">
<div class="modal-content">
<h3 id="modalTitle">加密导出</h3>
<h3 id="modalTitle" data-i18n="pwdModalExportTitle">加密导出</h3>
<div id="encryptToggleGroup" class="form-group modal-toggle">
<label class="toggle-label">
<input type="checkbox" id="encryptToggle" checked>
<span>加密导出文件</span>
<span data-i18n="encryptExportLabel">加密导出文件</span>
</label>
<small>勾选后用文件密码加密;不勾选则导出明文 JSON</small>
<small data-i18n="encryptExportHelp">勾选后用文件密码加密;不勾选则导出明文 JSON</small>
</div>
<div id="pwdFields" class="modal-fields">
<div class="form-group">
<label for="modalPwd">文件密码</label>
<label for="modalPwd" data-i18n="filePasswordLabel">文件密码</label>
<div class="password-wrapper">
<input type="password" id="modalPwd" placeholder="输入文件密码">
<button class="toggle-pwd eye-open" type="button" data-target="modalPwd" aria-label="切换密码显示">👁</button>
<input type="password" id="modalPwd" data-i18n-placeholder="filePasswordPlaceholder" placeholder="输入文件密码">
<button class="toggle-pwd eye-open" type="button" data-target="modalPwd" data-i18n-aria="togglePwdAria" aria-label="切换密码显示">👁</button>
</div>
</div>
<div class="form-group" id="confirmGroup">
<label for="modalPwdConfirm">确认文件密码</label>
<label for="modalPwdConfirm" data-i18n="filePasswordConfirmLabel">确认文件密码</label>
<div class="password-wrapper">
<input type="password" id="modalPwdConfirm" placeholder="再次输入文件密码">
<button class="toggle-pwd eye-open" type="button" data-target="modalPwdConfirm" aria-label="切换密码显示">👁</button>
<input type="password" id="modalPwdConfirm" data-i18n-placeholder="filePasswordConfirmPlaceholder" placeholder="再次输入文件密码">
<button class="toggle-pwd eye-open" type="button" data-target="modalPwdConfirm" data-i18n-aria="togglePwdAria" aria-label="切换密码显示">👁</button>
</div>
</div>
<div class="modal-warn" id="modalWarn">文件密码将用于 AES-GCM 加密,无法找回,请妥善保存</div>
<div class="modal-warn" id="modalWarn" data-i18n="pwdModalExportWarn">文件密码将用于 AES-GCM 加密,无法找回,请妥善保存</div>
<div class="strength-block" id="strengthBlock">
<div class="strength-bar-bg">
<div class="strength-bar-fg" id="strengthBar"></div>
</div>
<div class="strength-info">
<span id="strengthLabel">尚未输入</span>
<span id="strengthLabel" data-i18n="strengthEmpty">尚未输入</span>
<span id="crackTime"></span>
</div>
</div>
</div>
<div class="modal-actions">
<button type="button" id="modalCancel" class="btn-edit">取消</button>
<button type="button" id="modalConfirm" class="btn-primary">确认</button>
<button type="button" id="modalCancel" class="btn-edit" data-i18n="cancelBtn">取消</button>
<button type="button" id="modalConfirm" class="btn-primary" data-i18n="confirmBtn">确认</button>
</div>
</div>
</div>