From 131421a0f10bb1c729dda7eb9a3b70c7da38393d Mon Sep 17 00:00:00 2001 From: zxyszx <299979470+zxyszx@users.noreply.github.com> Date: Mon, 10 Aug 2026 02:55:49 +0800 Subject: [PATCH] release: prepare v1.2.21 --- .github/release-notes/v1.2.21.md | 8 ++ README.md | 2 + VERSION | 2 +- apps/web/package.json | 2 +- apps/web/src/components/auth-guard.tsx | 10 +- apps/web/src/components/auth-states.tsx | 10 +- apps/web/src/components/ui/button.tsx | 10 +- apps/web/src/components/ui/card.tsx | 2 +- apps/web/src/components/ui/input.tsx | 2 +- apps/web/src/components/ui/select.tsx | 2 +- apps/web/src/components/ui/textarea.tsx | 2 +- apps/web/src/hooks/use-me.ts | 8 +- apps/web/src/index.css | 38 +++---- apps/web/src/lib/api.ts | 26 ++++- apps/web/src/lib/navigation.ts | 4 + apps/web/src/pages/admin.tsx | 82 +++++++++++--- apps/web/src/pages/login.tsx | 14 ++- apps/web/src/pages/mail.tsx | 115 ++++++++++++++++---- apps/web/src/pages/not-found.tsx | 4 +- apps/web/src/pages/profile.tsx | 135 +++++++++++++++--------- apps/web/src/pages/register.tsx | 8 +- apps/web/vite.config.ts | 51 ++++++--- docs/ISSUE_LEDGER.md | 9 +- pnpm-lock.yaml | 10 +- 24 files changed, 390 insertions(+), 166 deletions(-) create mode 100644 .github/release-notes/v1.2.21.md create mode 100644 apps/web/src/lib/navigation.ts diff --git a/.github/release-notes/v1.2.21.md b/.github/release-notes/v1.2.21.md new file mode 100644 index 0000000..afe15be --- /dev/null +++ b/.github/release-notes/v1.2.21.md @@ -0,0 +1,8 @@ +- 优化登录与会话流程:登录后完整返回原页面及查询条件,区分未登录、超时、取消和网络故障,并为服务不可用状态提供明确的重新连接入口。 +- 完善后台与邮箱错误处理:管理员设置、邮件列表、邮件详情、发送队列、个人资料、签名、DNS 检查及注册流程均增加真实失败提示和重试反馈,避免静默失败或错误成功提示。 +- 优化邮箱与个人设置:恢复显示名称编辑,新增可持久化的标准/紧凑邮件布局,移除无效时区和模拟资料,修正发信成功后草稿删除失败的提示逻辑。 +- 保持并强化转发规则:账号级转发目标在所有邮箱中默认勾选、置顶且不可取消,单邮箱可继续追加独立目标,现有单邮箱配置不受影响,目标按数字和字母排序。 +- 统一界面视觉与交互:采用更清晰的中性色、文字层级、焦点状态和紧凑圆角,补充图标按钮名称、工具提示及全屏页面主区域,改善桌面与移动端可访问性。 +- 优化前端加载与开发体验:拆分邮件编辑器相关代码包,控制单个构建文件体积,并支持通过 `VITE_API_TARGET` 指定本地后端代理地址。 +- 加固邮件 HTML 安全:升级 DOMPurify 至已修复版本,依赖审计无已知漏洞;同步清理过时演示数据、无效状态和旧页面逻辑。 +- 完成全量质量复核:前后端构建、Go 全量及竞态测试、SMTP、外部 IMAP、OAuth、Telegram、Webhook、转发、队列、权限隔离、安装、备份、回滚和 DKIM 同步测试均已通过。 diff --git a/README.md b/README.md index 86b5012..82d8fd8 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,8 @@ pnpm install pnpm run dev ``` +后端不在默认的 `http://localhost:8080` 时,可通过 `VITE_API_TARGET=http://localhost:18080 pnpm run dev` 指定本地代理目标。 + 提交前建议运行: ```bash diff --git a/VERSION b/VERSION index 1fc5b82..9728bd6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.15 +1.2.21 diff --git a/apps/web/package.json b/apps/web/package.json index 6b07435..8ae3258 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -36,7 +36,7 @@ "@tiptap/starter-kit": "^3.27.0", "class-variance-authority": "^0.7.0", "clsx": "2.1.1", - "dompurify": "3.4.12", + "dompurify": "3.4.13", "lucide-react": "^0.468.0", "qrcode.react": "^4.2.0", "react": "18.3.1", diff --git a/apps/web/src/components/auth-guard.tsx b/apps/web/src/components/auth-guard.tsx index e632012..6a0f135 100644 --- a/apps/web/src/components/auth-guard.tsx +++ b/apps/web/src/components/auth-guard.tsx @@ -1,15 +1,19 @@ import React from "react" import { Navigate, useLocation } from "react-router-dom" -import { useMe, isTimeoutError } from "@/hooks/use-me" +import { useMe } from "@/hooks/use-me" import { AuthLoading, AuthError } from "@/components/auth-states" +import { isUnauthorizedError } from "@/lib/api" export function AuthGuard({ children }: { children: React.ReactNode }) { const me = useMe() const location = useLocation() if (me.isLoading) return - if (me.isError && isTimeoutError(me.error)) return me.refetch()} /> - if (me.isError || !me.data?.user) return + if (me.isError && !isUnauthorizedError(me.error)) return me.refetch()} /> + if (me.isError || !me.data?.user) { + const from = `${location.pathname}${location.search}${location.hash}` + return + } return <>{children} } diff --git a/apps/web/src/components/auth-states.tsx b/apps/web/src/components/auth-states.tsx index cf9b865..28e8fbc 100644 --- a/apps/web/src/components/auth-states.tsx +++ b/apps/web/src/components/auth-states.tsx @@ -1,17 +1,17 @@ import { Button } from "@/components/ui/button" export function AuthLoading() { - return
加载中...
+ return
加载中...
} export function AuthError({ message, onRetry }: { message: string; onRetry: () => void }) { return ( -
+
-
无法连接后端服务
+
服务暂时不可用
{message}
- +
-
+ ) } diff --git a/apps/web/src/components/ui/button.tsx b/apps/web/src/components/ui/button.tsx index 65d4fcd..71c36f3 100644 --- a/apps/web/src/components/ui/button.tsx +++ b/apps/web/src/components/ui/button.tsx @@ -5,18 +5,18 @@ import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", { variants: { variant: { default: - "bg-primary text-primary-foreground shadow hover:bg-primary/90", + "bg-primary text-primary-foreground hover:bg-primary/90", destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", secondary: - "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", }, diff --git a/apps/web/src/components/ui/card.tsx b/apps/web/src/components/ui/card.tsx index cabfbfc..378b5d1 100644 --- a/apps/web/src/components/ui/card.tsx +++ b/apps/web/src/components/ui/card.tsx @@ -9,7 +9,7 @@ const Card = React.forwardRef<
>( span]:line-clamp-1", + "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className )} {...props} diff --git a/apps/web/src/components/ui/textarea.tsx b/apps/web/src/components/ui/textarea.tsx index e56b0af..73063e8 100644 --- a/apps/web/src/components/ui/textarea.tsx +++ b/apps/web/src/components/ui/textarea.tsx @@ -9,7 +9,7 @@ const Textarea = React.forwardRef< return (