From cefc86917d897a3403d88748bbd869079f55c500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=80=BB=E5=B7=A5?= Date: Sat, 29 Aug 2026 13:14:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(HEL-233):=20=E5=8E=BB=E6=8E=89=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E6=8C=89=E9=92=AE=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=A4=9A=E4=BD=99=E5=BC=95=E5=8F=B7=EF=BC=8C=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E7=82=B9=E5=87=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 五个无值 data-system-* 属性名后多写了引号,选择器匹配失败导致按钮完全无效。 toast 改为在未打开抽屉时也能挂载,并补源码与真实点击回归。 Co-authored-by: Cursor Co-authored-by: multica-agent --- frontend/m/js/pages.js | 12 ++++++------ tests/e2e/mobile-app.spec.js | 12 ++++++++++++ tests/test_mobile_system_pages.py | 19 +++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/frontend/m/js/pages.js b/frontend/m/js/pages.js index 08a53c9..8e78515 100644 --- a/frontend/m/js/pages.js +++ b/frontend/m/js/pages.js @@ -3466,7 +3466,7 @@ } function showToast(message) { - const root = document.getElementById("m-sheet-root"); + const root = ensureSheetRoot(); if (!root) return; let toast = document.getElementById("m-toast"); if (!toast) { @@ -4966,7 +4966,7 @@ const page = document.querySelector(".m-page"); if (page) { page.innerHTML = '
' + html + "
" + - '
'; + '
'; } } @@ -4981,7 +4981,7 @@ const page = document.querySelector(".m-page"); if (page) { page.innerHTML = '
' + html + "
" + - '
'; + '
'; } } @@ -5058,13 +5058,13 @@ formFieldHtml("主模型", '', false) + formFieldHtml("辅助模型", '', false) + '
' + renderModelPoolHtml(llm.models || []) + "
" + - '' + + '' + ""; const page = document.querySelector(".m-page"); if (!page) return; const bar = tab === "models" - ? '
' - : '
'; + ? '
' + : '
'; page.innerHTML = adminTabHtml() + '
' + (tab === "models" ? modelsHtml : marketHtml) + "
" + bar; if (tab === "models") updateSystemModelRoleOptions(llm.primary_model_id || "", llm.fallback_model_id || ""); } diff --git a/tests/e2e/mobile-app.spec.js b/tests/e2e/mobile-app.spec.js index 991431f..e532b7e 100644 --- a/tests/e2e/mobile-app.spec.js +++ b/tests/e2e/mobile-app.spec.js @@ -355,6 +355,18 @@ test("system management pages render real content instead of placeholders", asyn await expect(page.locator("#m-sys-member-limit")).toBeVisible(); }); +test("empty profile save click shows a toast instead of a dead button", async ({ page }) => { + await mockMobileApi(page); + await openMobile(page); + await navigateToFeature(page, "system/profile"); + await expect(page.locator("[data-system-save-birth]")).toBeVisible(); + await page.locator("#m-sys-birth-date").fill(""); + await page.locator("#m-sys-birth-time").fill(""); + await page.locator("[data-system-save-birth]").click(); + await expect(page.locator("#m-toast.is-visible")).toBeVisible(); + await expect(page.locator("#m-toast")).toContainText("请填写完整出生日期和时间"); +}); + test("non-admin cannot open system admin pages as placeholders", async ({ page }) => { await mockMobileApi(page, { auth: authSession("user", true) }); await openMobile(page); diff --git a/tests/test_mobile_system_pages.py b/tests/test_mobile_system_pages.py index 6eb033c..4634819 100644 --- a/tests/test_mobile_system_pages.py +++ b/tests/test_mobile_system_pages.py @@ -57,3 +57,22 @@ class MobileSystemPagesRegressionTests(unittest.TestCase): 'location.assign("/login/")', ): self.assertIn(marker, pages) + + def test_system_boolean_attrs_do_not_have_stray_quotes(self) -> None: + pages = PAGES.read_text(encoding="utf-8") + stray = re.findall(r'data-system-[a-z-]*"(?=[>\s])', pages) + self.assertEqual( + stray, + [], + "boolean data-system attributes must not have a trailing quote before > or space", + ) + for name in ( + "data-system-save-birth", + "data-system-save-password", + "data-system-add-model", + "data-system-save-models", + "data-system-save-market", + "data-system-refresh", + ): + self.assertIn(name, pages) + self.assertNotIn(name + '">', pages)