From 830ca85ebd71d884bf2bf9f5ce7a0772ecdaacc5 Mon Sep 17 00:00:00 2001 From: bigcode Date: Thu, 1 Oct 2026 01:11:06 +0800 Subject: [PATCH] =?UTF-8?q?v2.5.1:=20=E9=82=AE=E4=BB=B6=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E6=8A=BD=E5=B1=89=E5=8E=BB=E6=8E=89=20=E9=82=AE=E7=AE=B1/Messa?= =?UTF-8?q?ge-ID;=E6=B7=BB=E5=8A=A0=E8=B4=A6=E5=8F=B7=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=8E=BB=E5=88=87=E6=8D=A2=E6=8E=A7=E4=BB=B6,OAuth=20=E6=8C=89?= =?UTF-8?q?=E9=92=AE=20+=20API=20Token=20=E8=A1=A8=E5=8D=95=E5=B9=B3?= =?UTF-8?q?=E9=93=BA=E5=90=8C=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- console/frontend/src/pages/Accounts.tsx | 59 ++++++++----------------- console/frontend/src/pages/Inbox.tsx | 4 -- package.json | 2 +- tests/ui-smoke.ts | 35 +++++++-------- 4 files changed, 36 insertions(+), 64 deletions(-) diff --git a/console/frontend/src/pages/Accounts.tsx b/console/frontend/src/pages/Accounts.tsx index 2467549..a2db0db 100644 --- a/console/frontend/src/pages/Accounts.tsx +++ b/console/frontend/src/pages/Accounts.tsx @@ -1,4 +1,4 @@ -/** 账号页:添加账号(Cloudflare OAuth / API Token 同窗切换),授权后自动接入并同步域名;搜索、详情、凭据管理 */ +/** 账号页:添加账号(Cloudflare OAuth / API Token 同窗平铺),授权后自动接入并同步域名;搜索、详情、凭据管理 */ import { useCallback, useEffect, useMemo, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { @@ -9,7 +9,6 @@ import { Form, Input, Modal, - Radio, Space, Table, Tag, @@ -123,8 +122,6 @@ export function AccountsPage() { /** 添加账号:OAuth 与 API Token 两种方式都收在同一个模态窗口里 */ const [addOpen, setAddOpen] = useState(false); - /** 当前选中的授权方式 **/ - const [addMode, setAddMode] = useState<"oauth" | "token">("oauth"); /** API Token 提交的 loading(要防重复点击,一次接入要走好几次 Cloudflare 调用) **/ const [adding, setAdding] = useState(false); const [tokenForm] = Form.useForm(); @@ -270,10 +267,8 @@ export function AccountsPage() { { if (adding) return; setAddOpen(false); @@ -299,22 +294,20 @@ export function AccountsPage() { /** # 成员变量: 添加账号模态窗口的属性 **/ interface AddAccountModalProps { open: boolean; - mode: "oauth" | "token"; loading: boolean; form: ReturnType[0]; - onModeChange: (mode: "oauth" | "token") => void; onCancel: () => void; onOAuth: () => void; onTokenSubmit: () => void; } /** # 函数 - * 「添加 Cloudflare 账号」模态窗口:Cloudflare OAuth 授权与 API Token 授权在同一个窗口, - * 顶部按钮组切换方式,字段随方式变化 —— OAuth 只要一个「前往授权」按钮, - * API Token 填账户名称 + Token 即可(账户 ID 由 Token 在 Cloudflare 侧实际所属账户自动确定)。 + * 「添加 Cloudflare 账号」模态窗口:两种授权方式平铺展示、无需切换 —— + * 顶部「Cloudflare OAuth 授权」一键跳转授权,分隔线下方是 API Token 表单 + * (账户名称 + Token,账户 ID 由 Token 在 Cloudflare 侧实际所属账户自动确定)。 */ function AddAccountModal(props: AddAccountModalProps) { - const { open, mode, loading, form, onModeChange, onCancel, onOAuth, onTokenSubmit } = props; + const { open, loading, form, onCancel, onOAuth, onTokenSubmit } = props; return ( - onModeChange(e.target.value as "oauth" | "token")} - style={{ marginBottom: 4 }} - > - - Cloudflare OAuth 授权 - - - API Token 授权 - - + - {mode === "oauth" ? ( - - ) : ( - - - - - - - - - - )} + ); } diff --git a/console/frontend/src/pages/Inbox.tsx b/console/frontend/src/pages/Inbox.tsx index 6270fa4..2d5c861 100644 --- a/console/frontend/src/pages/Inbox.tsx +++ b/console/frontend/src/pages/Inbox.tsx @@ -340,10 +340,6 @@ export function InboxPage() { {safeArr(detail.email.to_addresses).join(", ") || "-"} - {detail.email.mailbox_address ?? "(未匹配)"} - - {detail.email.message_id ?? "-"} - {new Date(detail.email.received_at).toLocaleString()} →{" "} {detail.email.retained ? ( diff --git a/package.json b/package.json index 5cd1e8b..a0609c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wmailhub", - "version": "2.5.0", + "version": "2.5.1", "description": "WmailHub - 基于 Cloudflare Email Workers 的轻量邮件接收与转发平台(Console 直连 Email Worker)", "private": true, "type": "module", diff --git a/tests/ui-smoke.ts b/tests/ui-smoke.ts index 041fc65..74576d5 100644 --- a/tests/ui-smoke.ts +++ b/tests/ui-smoke.ts @@ -84,6 +84,12 @@ await page.locator(".ant-table-row").first().click(); await page.waitForSelector(".ant-drawer-open", { timeout: 8000 }); const drawerText = (await page.locator(".ant-drawer-title").textContent()) ?? ""; check("邮件详情抽屉打开(标题=邮件主题)", drawerText.trim().length > 0, drawerText.trim()); +check( + "详情抽屉不再展示「邮箱」/「Message-ID」", + (await page.locator(".ant-drawer .ant-descriptions-item-label:has-text('邮箱')").count()) === 0 && + (await page.locator(".ant-drawer .ant-descriptions-item-label:has-text('Message-ID')").count()) === 0, +); +await page.waitForTimeout(500); // 等抽屉滑入动画结束再截图 await page.screenshot({ path: `${SHOT_DIR}/08-email-detail.png` }); await page.keyboard.press("Escape"); @@ -144,7 +150,7 @@ for (const path of ["/accounts", "/domains", "/mailboxes", "/inboxs"]) { if (path === "/mailboxes") await page.screenshot({ path: `${SHOT_DIR}/11-batch-selected.png` }); } -// 6b. 添加账号模态窗口:OAuth / API Token 同窗(Radio 切换),只留必要字段 +// 6b. 添加账号模态窗口:OAuth 按钮 + API Token 表单同窗平铺,无需切换控件 await page.goto(`${BASE}/accounts`, { waitUntil: "domcontentloaded" }); await page.waitForSelector(".ant-table", { timeout: 8000 }); check( @@ -153,32 +159,25 @@ check( ); await page.click("button:has-text('添加账号')"); await page.waitForSelector(".ant-modal:has-text('添加 Cloudflare 账号')", { timeout: 8000 }); -const modeLabels = await page.locator(".ant-modal .ant-radio-button-wrapper").allInnerTexts(); check( - "添加账号模态窗口含 OAuth / API Token 两种授权方式(同窗按钮组)", - modeLabels.some((t) => t.includes("OAuth")) && modeLabels.some((t) => t.includes("API Token")), - modeLabels.join(" | "), + "两种授权方式同窗平铺(两个按钮 + 两个字段同时可见),无切换控件", + (await page.locator(".ant-modal button:has-text('Cloudflare OAuth 授权')").count()) === 1 && + (await page.locator(".ant-modal button:has-text('API Token 授权')").count()) === 1 && + (await page.locator(".ant-modal .ant-radio-button-wrapper").count()) === 0 && + (await page.locator(".ant-modal .ant-tabs-tab").count()) === 0 && + (await page.locator(".ant-modal:visible").count()) === 1, ); check( "窗口内不再有说明文字(Alert)与账户 ID 字段", (await page.locator(".ant-modal .ant-alert").count()) === 0 && (await page.locator(".ant-modal :text('账户 ID')").count()) === 0, ); -// OAuth 模式:只有「前往 Cloudflare 授权」按钮 check( - "OAuth 模式默认展示「前往 Cloudflare 授权」按钮", - (await page.locator(".ant-modal button:has-text('前往 Cloudflare 授权')").count()) === 1, + "API Token 表单只含 账户名称 / API Token 两个字段(1 个密码框)", + (await page.locator(".ant-modal input[type=password]").count()) === 1, ); -await page.screenshot({ path: `${SHOT_DIR}/12a-add-account-oauth.png` }); -// 切到 API Token:账户名称 + API Token 两个字段 -await page.click(".ant-modal .ant-radio-button-wrapper:has-text('API Token')"); -await page.waitForSelector(".ant-modal :text('账户名称')", { timeout: 8000 }); -check( - "API Token 方式只含 账户名称 / API Token 两个字段", - (await page.locator(".ant-modal input[type=password]").count()) === 1 && - (await page.locator(".ant-modal :text('账户 ID')").count()) === 0, -); -await page.screenshot({ path: `${SHOT_DIR}/12b-add-account-token.png` }); +await page.waitForTimeout(500); // 等开窗动画结束再截图 +await page.screenshot({ path: `${SHOT_DIR}/12a-add-account.png` }); await page.keyboard.press("Escape"); await page.waitForTimeout(400);