diff --git a/src/app/auth/components/auth-back-button.module.css b/src/app/auth/components/auth-back-button.module.css
new file mode 100644
index 00000000..f29ef8c0
--- /dev/null
+++ b/src/app/auth/components/auth-back-button.module.css
@@ -0,0 +1,29 @@
+.backButton {
+ position: absolute;
+ top: var(--spacing-xl);
+ left: var(--spacing-xl);
+ z-index: 2;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: var(--auth-back-button-size);
+ height: var(--auth-back-button-size);
+ padding: 0 2px 0 0;
+ color: var(--color-auth-text-primary);
+ cursor: pointer;
+ background: var(--color-auth-surface);
+ border: none;
+ border-radius: 50%;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ transition:
+ background 0.15s ease,
+ transform 0.05s ease;
+}
+
+.backButton:hover {
+ background: rgba(0, 0, 0, 0.04);
+}
+
+.backButton:active {
+ transform: scale(0.96);
+}
diff --git a/src/app/auth/components/auth-back-button.tsx b/src/app/auth/components/auth-back-button.tsx
new file mode 100644
index 00000000..5203cec9
--- /dev/null
+++ b/src/app/auth/components/auth-back-button.tsx
@@ -0,0 +1,22 @@
+"use client";
+
+import { ChevronLeft } from "lucide-react";
+
+import styles from "./auth-back-button.module.css";
+
+export interface AuthBackButtonProps {
+ onClick: () => void;
+}
+
+export function AuthBackButton({ onClick }: AuthBackButtonProps) {
+ return (
+
+ );
+}
diff --git a/src/app/auth/components/auth-background.module.css b/src/app/auth/components/auth-background.module.css
index a2613091..7ab89f18 100644
--- a/src/app/auth/components/auth-background.module.css
+++ b/src/app/auth/components/auth-background.module.css
@@ -4,7 +4,7 @@
position: absolute;
inset: 0;
z-index: 0;
- background: var(--color-page-background);
+ background: #fbf1f2;
overflow: hidden;
}
diff --git a/src/app/auth/components/auth-panel.module.css b/src/app/auth/components/auth-panel.module.css
index 2011d5ac..9161dfe0 100644
--- a/src/app/auth/components/auth-panel.module.css
+++ b/src/app/auth/components/auth-panel.module.css
@@ -2,7 +2,6 @@
*
* 视觉规格(与 Dart 对齐):
* - panelShell 包裹整个面板(position: relative)
- * - 悬浮返回按钮:40×40 白色圆形 + 淡黑阴影,固定 top/left 20px
*/
.panelShell {
position: relative;
@@ -12,31 +11,3 @@
width: 100%;
min-height: 0;
}
-
-.backButton {
- position: absolute;
- top: var(--spacing-xl);
- left: var(--spacing-xl);
- z-index: 2;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: var(--auth-back-button-size);
- height: var(--auth-back-button-size);
- border: none;
- border-radius: 50%;
- background: var(--color-auth-surface);
- color: var(--color-auth-text-primary);
- padding: 0 2px 0 0;
- cursor: pointer;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- transition: background 0.15s ease, transform 0.05s ease;
-}
-
-.backButton:hover {
- background: rgba(0, 0, 0, 0.04);
-}
-
-.backButton:active {
- transform: scale(0.96);
-}
diff --git a/src/app/auth/components/auth-panel.tsx b/src/app/auth/components/auth-panel.tsx
index 6fad6888..b33b28c3 100644
--- a/src/app/auth/components/auth-panel.tsx
+++ b/src/app/auth/components/auth-panel.tsx
@@ -3,10 +3,10 @@
* 认证面板:顶层 switch(Facebook / Email)+ 悬浮返回按钮
*/
import { useRouter } from "next/navigation";
-import { ChevronLeft } from "lucide-react";
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
+import { AuthBackButton } from "./auth-back-button";
import { AuthEmailPanel } from "./auth-email-panel";
import { AuthFacebookPanel } from "./auth-facebook-panel";
import styles from "./auth-panel.module.css";
@@ -29,14 +29,7 @@ export function AuthPanel() {
return (
-
+
{state.authPanelMode === "facebook" ? (
diff --git a/src/app/auth/components/auth-screen.module.css b/src/app/auth/components/auth-screen.module.css
index e340de27..4dcf4685 100644
--- a/src/app/auth/components/auth-screen.module.css
+++ b/src/app/auth/components/auth-screen.module.css
@@ -10,6 +10,7 @@
flex-direction: column;
width: 100%;
min-height: 100dvh;
+ background: #fbf1f2;
overflow: hidden;
}
diff --git a/src/app/auth/components/index.ts b/src/app/auth/components/index.ts
index 45497f29..fc76f775 100644
--- a/src/app/auth/components/index.ts
+++ b/src/app/auth/components/index.ts
@@ -3,6 +3,7 @@
*/
export * from "./auth-background";
+export * from "./auth-back-button";
export * from "./auth-divider";
export * from "./auth-email-panel";
export * from "./auth-error-message";
diff --git a/src/app/chat/components/index.ts b/src/app/chat/components/index.ts
index 7cf4da87..e0ca93c6 100644
--- a/src/app/chat/components/index.ts
+++ b/src/app/chat/components/index.ts
@@ -22,3 +22,4 @@ export * from "./message-content";
export * from "./pwa-install-dialog";
export * from "./pwa-install-overlay";
export * from "./text-bubble";
+export * from "./user-message-avatar";
diff --git a/src/app/chat/components/message-avatar.tsx b/src/app/chat/components/message-avatar.tsx
index 68abf8c1..fe723ffe 100644
--- a/src/app/chat/components/message-avatar.tsx
+++ b/src/app/chat/components/message-avatar.tsx
@@ -1,16 +1,7 @@
"use client";
-/**
- * MessageAvatar 消息头像
- *
- * 原始 Dart: lib/ui/chat/widgets/message_avatar.dart(85 行)
- *
- * 显示规则:
- * - AI 消息:Elio 头像(`/images/chat/pic-chat-elio.png`)
- * - 用户消息(有 avatarUrl):用户头像
- * - 用户消息(无 avatarUrl):游客头像(`/images/chat/pic-chat-guest.png`)
- */
import Image from "next/image";
+import { UserMessageAvatar } from "./user-message-avatar";
import styles from "./message-avatar.module.css";
export interface MessageAvatarProps {
@@ -33,22 +24,5 @@ export function MessageAvatar({ isFromAI, userAvatarUrl }: MessageAvatarProps) {
);
}
- if (userAvatarUrl && userAvatarUrl.length > 0) {
- return (
-
-
-
- );
- }
-
- return (
-
-
-
- );
+ return
;
}
diff --git a/src/app/chat/components/user-message-avatar.tsx b/src/app/chat/components/user-message-avatar.tsx
new file mode 100644
index 00000000..78b9e615
--- /dev/null
+++ b/src/app/chat/components/user-message-avatar.tsx
@@ -0,0 +1,30 @@
+"use client";
+
+import Image from "next/image";
+
+import styles from "./message-avatar.module.css";
+
+export interface UserMessageAvatarProps {
+ avatarUrl?: string | null;
+}
+
+export function UserMessageAvatar({ avatarUrl }: UserMessageAvatarProps) {
+ if (avatarUrl && avatarUrl.length > 0) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/src/app/subscription/components/subscription-screen.module.css b/src/app/subscription/components/subscription-screen.module.css
index 45891876..213cee68 100644
--- a/src/app/subscription/components/subscription-screen.module.css
+++ b/src/app/subscription/components/subscription-screen.module.css
@@ -3,7 +3,7 @@
flex-direction: column;
min-height: 100dvh;
background: var(--color-page-background);
- padding: 0 var(--spacing-lg) var(--spacing-xxl);
+ padding: 30px 20px 10px;
}
.header {
diff --git a/src/stores/payment/payment-state.ts b/src/stores/payment/payment-state.ts
index d3efb821..0aba2068 100644
--- a/src/stores/payment/payment-state.ts
+++ b/src/stores/payment/payment-state.ts
@@ -27,7 +27,7 @@ export const initialState: PaymentState = {
selectedPlanId: "",
payChannel: "stripe",
autoRenew: true,
- agreed: false,
+ agreed: true,
currentOrderId: null,
payParams: null,
orderStatus: null,