This commit is contained in:
2026-09-14 23:07:15 +08:00
parent 991cfe3c35
commit c4b08be4eb
3 changed files with 171 additions and 22 deletions
+15 -2
View File
@@ -294,7 +294,6 @@ h2 {
.lock-screen {
position: fixed;
inset: 0;
background: #0f0f1e;
display: flex;
align-items: center;
justify-content: center;
@@ -306,7 +305,6 @@ h2 {
max-width: 320px;
padding: 28px 24px;
text-align: center;
box-shadow: 0 8px 32px rgba(233, 69, 96, 0.15);
}
.lock-logo {
@@ -893,6 +891,21 @@ h2 {
flex: 1;
}
/* 编辑域名配置对话框:字段较多,允许滚动并加宽 */
.edit-config-content {
max-width: 380px;
max-height: 90vh;
overflow-y: auto;
}
.edit-config-content .modal-actions {
position: sticky;
bottom: 0;
background: #16213e;
padding-top: 10px;
margin-top: 12px;
}
/* 环境管理对话框列表 */
.env-manage-list {
display: flex;
+69
View File
@@ -223,6 +223,75 @@
</div>
</div>
<!-- 编辑域名配置对话框 -->
<div id="editConfigModal" class="modal">
<div class="modal-content edit-config-content">
<h3 data-i18n="editConfigTitle">编辑域名配置</h3>
<div class="form-group">
<label for="editDomain" data-i18n="domainLabel">域名 / URL 匹配规则</label>
<input type="text" id="editDomain" data-i18n-placeholder="domainPlaceholder" placeholder="example.com 或 *.example.com 或 site.com/admin/*">
<small data-i18n="domainHelp">支持通配符 *。带 / 时按 hostname+path 匹配,如 oa.com/login/*;不带 / 时只匹配域名</small>
</div>
<div class="form-group">
<label for="editUsername" data-i18n="usernameLabel">用户名</label>
<input type="text" id="editUsername" data-i18n-placeholder="usernamePlaceholder" placeholder="输入用户名">
</div>
<div class="form-group">
<label for="editPassword" data-i18n="passwordLabel">密码</label>
<div class="password-wrapper">
<input type="password" id="editPassword" data-i18n-placeholder="passwordPlaceholder" placeholder="输入密码">
<button class="toggle-pwd eye-open" type="button" data-target="editPassword" data-i18n-aria="togglePwdAria" aria-label="切换密码显示">👁</button>
</div>
</div>
<div class="form-group">
<label for="editAlias" data-i18n="aliasLabel">别名(可选)</label>
<input type="text" id="editAlias" data-i18n-placeholder="aliasPlaceholder" placeholder="例如: 公司OA、GitLab、邮箱">
<small data-i18n="aliasHelp">方便识别该配置,留空则显示域名</small>
</div>
<details class="advanced-options">
<summary data-i18n="advancedOptionsSummary">高级选项(选填,默认即可)</summary>
<div class="advanced-options-body">
<div class="form-group">
<label for="editAutoSubmit" data-i18n="autoSubmitLabel">自动提交登录</label>
<select id="editAutoSubmit">
<option value="true" data-i18n="autoSubmitYes">是 - 自动点击登录按钮</option>
<option value="false" data-i18n="autoSubmitNo">否 - 仅填充不提交</option>
</select>
</div>
<div class="form-group">
<label for="editEnabled" data-i18n="enabledLabel">启用 / 禁用</label>
<label class="toggle-switch">
<input type="checkbox" id="editEnabled" checked>
<span class="toggle-slider"></span>
</label>
<small data-i18n="enabledHelp">禁用后该条配置将不会生效</small>
</div>
<div class="form-group">
<label for="editDelayMs" data-i18n="delayMsLabel">填充延迟(毫秒,可选)</label>
<input type="number" id="editDelayMs" 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="form-group">
<label data-i18n="usernameSelectorLabel">用户名输入框位置</label>
<input type="text" id="editUsernameSelector" data-i18n-placeholder="usernameSelectorPlaceholder" placeholder="留空=自动查找,如 #username 或 input[name=account]">
</div>
<div class="form-group">
<label data-i18n="passwordSelectorLabel">密码输入框位置</label>
<input type="text" id="editPasswordSelector" data-i18n-placeholder="passwordSelectorPlaceholder" placeholder="留空=自动查找,如 #password 或 input[type=password]">
</div>
<div class="form-group">
<label data-i18n="submitSelectorLabel">登录按钮位置</label>
<input type="text" id="editSubmitSelector" data-i18n-placeholder="submitSelectorPlaceholder" placeholder="留空=自动查找,如 #loginBtn 或 button[type=submit]">
</div>
</div>
</details>
<div class="modal-actions">
<button type="button" id="editConfigCancel" class="btn-edit" data-i18n="cancelBtn">取消</button>
<button type="button" id="editConfigSave" class="btn-primary" data-i18n="updateConfigBtn">更新配置</button>
</div>
</div>
</div>
<script src="utils.js"></script>
<script src="env-store.js"></script>
<script src="crypto-store.js"></script>
+87 -20
View File
@@ -66,6 +66,22 @@ document.addEventListener("DOMContentLoaded", () => {
const importFile = $("importFile");
const toast = $("toast");
// 编辑配置弹窗
const editConfigModal = $("editConfigModal");
const editDomainInput = $("editDomain");
const editUsernameInput = $("editUsername");
const editPasswordInput = $("editPassword");
const editAliasInput = $("editAlias");
const editAutoSubmitSelect = $("editAutoSubmit");
const editEnabledCheckbox = $("editEnabled");
const editDelayMsInput = $("editDelayMs");
const editUsernameSelectorInput = $("editUsernameSelector");
const editPasswordSelectorInput = $("editPasswordSelector");
const editSubmitSelectorInput = $("editSubmitSelector");
const editConfigCancel = $("editConfigCancel");
const editConfigSave = $("editConfigSave");
let editModalEditingId = null;
// 锁定界面
const lockScreen = $("lockScreen");
const mainContainer = $("mainContainer");
@@ -429,10 +445,11 @@ document.addEventListener("DOMContentLoaded", () => {
submitSelectorInput.value = draft.submitSelector || "";
enabledCheckbox.checked = draft.enabled !== false;
delayMsInput.value = draft.delayMs || "";
editingId = draft.editingId || null;
addBtn.textContent = editingId ? t("updateConfigBtn") : t("addConfigBtn");
addConfigTitleEl.textContent = editingId ? t("editConfigTitle") : t("addConfigTitle");
cancelEditBtn.hidden = !editingId;
editingId = null;
// 编辑已改为弹窗,顶部表单仅用于新增;忽略历史 draft 中的 editingId
addBtn.textContent = t("addConfigBtn");
addConfigTitleEl.textContent = t("addConfigTitle");
cancelEditBtn.hidden = true;
}
function clearDraft() {
@@ -706,22 +723,19 @@ document.addEventListener("DOMContentLoaded", () => {
editBtn.className = "btn-edit";
editBtn.textContent = t("editBtn");
editBtn.addEventListener("click", () => {
editingId = cfg.id;
domainInput.value = cfg.domain;
aliasInput.value = cfg.alias || "";
usernameInput.value = cfg.username;
passwordInput.value = cfg.password;
autoSubmitSelect.value = String(cfg.autoSubmit);
usernameSelectorInput.value = cfg.usernameSelector || "";
passwordSelectorInput.value = cfg.passwordSelector || "";
submitSelectorInput.value = cfg.submitSelector || "";
enabledCheckbox.checked = cfg.enabled !== false;
delayMsInput.value = cfg.delayMs || "";
addBtn.textContent = t("updateConfigBtn");
addConfigTitleEl.textContent = t("editConfigTitle");
cancelEditBtn.hidden = false;
saveDraft();
domainInput.focus();
editModalEditingId = cfg.id;
editDomainInput.value = cfg.domain;
editAliasInput.value = cfg.alias || "";
editUsernameInput.value = cfg.username;
editPasswordInput.value = cfg.password;
editAutoSubmitSelect.value = String(cfg.autoSubmit);
editUsernameSelectorInput.value = cfg.usernameSelector || "";
editPasswordSelectorInput.value = cfg.passwordSelector || "";
editSubmitSelectorInput.value = cfg.submitSelector || "";
editEnabledCheckbox.checked = cfg.enabled !== false;
editDelayMsInput.value = cfg.delayMs || "";
editConfigModal.classList.add("show");
editDomainInput.focus();
});
const delBtn = document.createElement("button");
@@ -816,6 +830,59 @@ document.addEventListener("DOMContentLoaded", () => {
if (envManageModal.classList.contains("show")) renderEnvManageList();
});
// 编辑配置弹窗:保存
editConfigSave.addEventListener("click", async () => {
const domain = editDomainInput.value.trim();
const username = editUsernameInput.value.trim();
const password = editPasswordInput.value;
if (!domain || !username || !password) {
showToast(t("toastRequired"));
return;
}
const config = {
id: editModalEditingId,
domain,
alias: editAliasInput.value.trim() || null,
username,
password,
autoSubmit: editAutoSubmitSelect.value === "true",
usernameSelector: editUsernameSelectorInput.value.trim() || null,
passwordSelector: editPasswordSelectorInput.value.trim() || null,
submitSelector: editSubmitSelectorInput.value.trim() || null,
enabled: editEnabledCheckbox.checked,
delayMs: editDelayMsInput.value ? Number(editDelayMsInput.value) : null,
};
const configs = await loadConfigs();
const idx = configs.findIndex((c) => c.id === editModalEditingId);
if (idx !== -1) {
configs[idx] = config;
}
await saveConfigs(configs);
editConfigModal.classList.remove("show");
editModalEditingId = null;
renderConfigList();
renderEnvSelect();
if (envManageModal.classList.contains("show")) renderEnvManageList();
showToast(t("toastUpdated"));
});
// 编辑配置弹窗:取消
editConfigCancel.addEventListener("click", () => {
editConfigModal.classList.remove("show");
editModalEditingId = null;
});
// 点击遮罩关闭编辑弹窗
editConfigModal.addEventListener("click", (e) => {
if (e.target === editConfigModal) {
editConfigModal.classList.remove("show");
editModalEditingId = null;
}
});
fillCurrentBtn.addEventListener("click", async () => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab) {