diff --git a/src/app/chat/components/chat-screen.tsx b/src/app/chat/components/chat-screen.tsx
index a2f601ae..346e8ee7 100644
--- a/src/app/chat/components/chat-screen.tsx
+++ b/src/app/chat/components/chat-screen.tsx
@@ -7,14 +7,12 @@
* 职责(本文件):
* - **订阅 auth 状态机**(loginStatus)—— 派生 isGuest / **派鉴权生命周期事件**给 chat 机器
* - 屏幕生命周期事件(init / visible / invisible)
- * - 配额告警监听(**仅**游客 —— "非游客无消息限制"业务事实)
* - **不**直接管理 WebSocket / **不**直接读 AuthStorage(除 token 取值)
*
* 子组件职责:
* - ChatHeader:顶部栏(游客 banner / 菜单按钮)
* - ChatArea:消息列表
* - ChatInputBar:输入栏(文字 + 发送 + More)
- * - QuotaDialog:配额告警弹窗(**仅**游客)
* - PwaInstallOverlay:PWA 安装提示触发器
* - BrowserHintOverlay:浏览器提示
*
@@ -26,14 +24,13 @@
* - `ChatLogout` → 登出(机器自动 cleanup WS actor)
* - chat 机器**内部**用 fromCallback actor 完整管理 WS 生命周期
*/
-import { useEffect, useRef, useState } from "react";
+import { useEffect, useRef } from "react";
import Image from "next/image";
import { useAuthState } from "@/stores/auth/auth-context";
import type { LoginStatus } from "@/models/auth/login-status";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { useChatDispatch, useChatState } from "@/stores/chat/chat-context";
-import { GuestChatQuota } from "@/stores/chat";
import { MobileShell } from "@/app/_components/core/mobile-shell";
@@ -42,7 +39,6 @@ import { ChatArea } from "./chat-area";
import { ChatHeader } from "./chat-header";
import { ChatInputBar } from "./chat-input-bar";
import { PwaInstallOverlay } from "./pwa-install-overlay";
-import { QuotaDialog } from "./quota-dialog";
import styles from "./chat-screen.module.css";
/**
@@ -88,9 +84,6 @@ export function ChatScreen() {
// isGuest 派生(chat-screen 是**唯一**知道这个值的地方 —— chat 机器无 isGuest 字段)
const isGuest = deriveIsGuest(authState.loginStatus);
- const [quotaDialogOpen, setQuotaDialogOpen] = useState(false);
- const [quotaExhausted, setQuotaExhausted] = useState(false);
-
// ─────────────────────────────────────────────────────────────
// 屏幕生命周期 + 派初次鉴权生命周期事件
// ─────────────────────────────────────────────────────────────
@@ -121,36 +114,6 @@ export function ChatScreen() {
dispatchAuthLifecycle(authState.loginStatus, chatDispatch);
}, [authState.loginStatus, chatDispatch]);
- // ─────────────────────────────────────────────────────────────
- // 配额耗尽触发器(**仅**游客 —— "非游客无消息限制")
- // ─────────────────────────────────────────────────────────────
- const prevTriggerRef = useRef(state.quotaExceededTrigger);
- useEffect(() => {
- if (!isGuest) return; // ← 防御:非游客 backend 不会发 ChatQuotaExceeded
- if (
- state.quotaExceededTrigger !== prevTriggerRef.current &&
- state.quotaExceededTrigger > 0
- ) {
- setQuotaExhausted(true);
- setQuotaDialogOpen(true);
- }
- prevTriggerRef.current = state.quotaExceededTrigger;
- }, [state.quotaExceededTrigger, isGuest]);
-
- // 配额警告(剩余 = 5)—— **仅**游客
- const prevRemainingRef = useRef(state.guestRemainingQuota);
- useEffect(() => {
- if (
- isGuest && // ← 派生自 auth.loginStatus
- state.guestRemainingQuota === GuestChatQuota.warningThreshold &&
- prevRemainingRef.current !== state.guestRemainingQuota
- ) {
- setQuotaExhausted(false);
- setQuotaDialogOpen(true);
- }
- prevRemainingRef.current = state.guestRemainingQuota;
- }, [state.guestRemainingQuota, isGuest]);
-
return (
@@ -183,13 +146,6 @@ export function ChatScreen() {
{/* PWA 安装提示触发器(无可见 UI,3.5s 后弹 dialog) */}
-
- {/* 配额告警弹窗(**仅**游客,gate 在 isGuest) */}
-
setQuotaDialogOpen(false)}
- isExhausted={quotaExhausted}
- />
);
diff --git a/src/app/chat/components/quota-dialog.module.css b/src/app/chat/components/quota-dialog.module.css
deleted file mode 100644
index b666afcf..00000000
--- a/src/app/chat/components/quota-dialog.module.css
+++ /dev/null
@@ -1,85 +0,0 @@
-/* QuotaDialog 配额提示弹窗样式 */
-
-.overlay {
- position: fixed;
- inset: 0;
- background: rgba(0, 0, 0, 0.5);
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 50;
-}
-
-.dialog {
- width: calc(100% - 40px);
- max-width: 360px;
- background: var(--color-surface, #1f1a2e);
- border-radius: var(--radius-lg, 12px);
- padding: var(--spacing-5, 20px);
- box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
- display: flex;
- flex-direction: column;
- align-items: center;
- text-align: center;
-}
-
-.icon {
- width: 64px;
- height: 64px;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 32px;
- margin-bottom: var(--spacing-4, 16px);
-}
-
-.iconExhausted {
- background: rgba(255, 80, 80, 0.2);
- color: #ff5050;
-}
-
-.iconWarning {
- background: rgba(248, 77, 150, 0.2);
- color: var(--color-accent, #f84d96);
-}
-
-.title {
- font-size: var(--font-size-lg, 18px);
- font-weight: 600;
- margin: 0 0 var(--spacing-2, 8px);
- color: var(--color-text-primary, #fff);
-}
-
-.content {
- font-size: var(--font-size-sm, 14px);
- line-height: 1.5;
- color: var(--color-text-secondary, #9e9e9e);
- margin: 0 0 var(--spacing-5, 20px);
-}
-
-.actions {
- display: flex;
- gap: var(--spacing-3, 12px);
- width: 100%;
-}
-
-.btn {
- flex: 1 1 auto;
- height: 40px;
- border: 0;
- border-radius: var(--radius-md, 8px);
- font-size: var(--font-size-base, 14px);
- font-weight: 600;
- cursor: pointer;
-}
-
-.btnSecondary {
- background: transparent;
- color: var(--color-text-primary, #fff);
-}
-
-.btnPrimary {
- background: var(--color-accent, #f84d96);
- color: #fff;
-}
diff --git a/src/app/chat/components/quota-dialog.tsx b/src/app/chat/components/quota-dialog.tsx
deleted file mode 100644
index 37c344fe..00000000
--- a/src/app/chat/components/quota-dialog.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-"use client";
-/**
- * QuotaDialog 配额提示弹窗
- *
- * 原始 Dart: lib/ui/chat/widgets/quota_dialog.dart(130 行)
- *
- * 两种模式:
- * - 警告模式(isExhausted=false):剩余配额 < 5 时,提示用户登录
- * - 耗尽模式(isExhausted=true):配额已用完,强制登录
- */
-import { useRouter } from "next/navigation";
-
-import { ROUTES } from "@/router/routes";
-
-import styles from "./quota-dialog.module.css";
-
-export interface QuotaDialogProps {
- open: boolean;
- onClose: () => void;
- isExhausted: boolean;
-}
-
-export function QuotaDialog({ open, onClose, isExhausted }: QuotaDialogProps) {
- const router = useRouter();
-
- if (!open) return null;
-
- const title = isExhausted
- ? "Daily quota exhausted"
- : "Login for unlimited access!";
-
- const content = isExhausted
- ? "Login to continue chatting~"
- : "Dear, sign up now and all your chats with Elio will be saved forever. In guest mode, your chat history will be deleted when you leave, and Elio will forget you.";
-
- const handleLogin = () => {
- onClose();
- router.push(ROUTES.auth);
- };
-
- return (
-
-
-
- {isExhausted ? "🚫" : "⚠️"}
-
-
-
- {title}
-
-
{content}
-
-
-
-
-
-
-
- );
-}
diff --git a/src/router/routes.ts b/src/router/routes.ts
index f1f3ad93..668ef8fb 100644
--- a/src/router/routes.ts
+++ b/src/router/routes.ts
@@ -10,7 +10,7 @@
* - 动态深链通过 `ROUTE_BUILDERS` 函数生成,避免手拼字符串。
*
* 注意:proxy 路由跳转逻辑(2026-06-15 迁出),但本文件的**类型化常量**仍在
- * 被 9 个组件(auth-screen / chat-header / quota-dialog / DeepLinkPersist /
+ * 被 8 个组件(auth-screen / chat-header / DeepLinkPersist /
* error / not-found / page / sidebar-screen / splash-screen)使用 —— **不能**整体注释。
*/