feat: move debug overlay to MobileLayout (全局持久显示)
This commit is contained in:
0
backend/serv.sh
Executable file → Normal file
0
backend/serv.sh
Executable file → Normal file
@@ -1,14 +1,27 @@
|
||||
import { Outlet } from "react-router";
|
||||
import { useUser } from "../context/UserContext";
|
||||
|
||||
/**
|
||||
* H5 移动端全局布局容器
|
||||
* - max-w-md (448px) 限制最大宽度,大屏居中显示
|
||||
* - min-h-dvh 使用动态视口高度,解决 Safari 地址栏问题
|
||||
* - safe-area padding 适配刘海屏/底部手势条
|
||||
*/
|
||||
export function MobileLayout() {
|
||||
const { debugInfo, clearDebug } = useUser();
|
||||
|
||||
return (
|
||||
<div className="max-w-md mx-auto min-h-dvh relative bg-morandi-50 shadow-[0_0_40px_rgba(0,0,0,0.06)]">
|
||||
{/* 全局调试浮层:所有页面下可见 */}
|
||||
{debugInfo.length > 0 && (
|
||||
<div
|
||||
className="absolute top-0 left-0 right-0 z-50 bg-black/80 text-green-400 text-xs p-3 overflow-auto max-h-[50%] cursor-pointer font-mono"
|
||||
style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', lineHeight: 1.5 }}
|
||||
onClick={() => clearDebug()}
|
||||
>
|
||||
<div style={{ borderBottom: '1px solid #0f0', paddingBottom: 4, marginBottom: 4, fontWeight: 'bold', fontSize: 14 }}>H5应用调试</div>
|
||||
{debugInfo.map((msg, i) => (
|
||||
<div key={i}>{msg}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -187,6 +187,9 @@ interface UserContextValue {
|
||||
setToken: (token: string) => void;
|
||||
setTokenAndUser: (token: string, info: BasicUserInfo) => void;
|
||||
fetchProfile: () => Promise<UserProfileDTO | null>;
|
||||
debugInfo: string[];
|
||||
addDebug: (msg: string) => void;
|
||||
clearDebug: () => void;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
@@ -195,6 +198,14 @@ const UserContext = createContext<UserContextValue | null>(null);
|
||||
export function UserProvider({ children }: { children: ReactNode }) {
|
||||
const [user, setUser] = useState<UserProfile>(loadProfile);
|
||||
const [token, setTokenState] = useState<string | null>(getToken);
|
||||
const [debugInfo, setDebugInfo] = useState<string[]>([]);
|
||||
const addDebug = useCallback((msg: string) => {
|
||||
console.log(msg);
|
||||
setDebugInfo(prev => [...prev.slice(-20), msg]);
|
||||
}, []);
|
||||
const clearDebug = useCallback(() => {
|
||||
setDebugInfo([]);
|
||||
}, []);
|
||||
|
||||
const setToken = useCallback((newToken: string) => {
|
||||
// 清理前一个用户的本地数据,防止用户间数据残留
|
||||
@@ -280,7 +291,7 @@ export function UserProvider({ children }: { children: ReactNode }) {
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<UserContext.Provider value={{ user, token, updateUser, updateUserRemote, setToken, setTokenAndUser, fetchProfile, logout }}>
|
||||
<UserContext.Provider value={{ user, token, updateUser, updateUserRemote, setToken, setTokenAndUser, fetchProfile, debugInfo, addDebug, clearDebug, logout }}>
|
||||
{children}
|
||||
</UserContext.Provider>
|
||||
);
|
||||
|
||||
@@ -10,11 +10,7 @@ export function LoginPage() {
|
||||
const navigate = useNavigate();
|
||||
const { setTokenAndUser, fetchProfile } = useUser();
|
||||
const [error, setError] = useState("");
|
||||
const [debugInfo, setDebugInfo] = useState<string[]>([]);
|
||||
const addDebug = (msg: string) => {
|
||||
console.log(msg);
|
||||
setDebugInfo(prev => [...prev.slice(-20), msg]);
|
||||
};
|
||||
const { addDebug, debugInfo } = useUser();
|
||||
|
||||
useEffect(() => {
|
||||
clearDebugLogs();
|
||||
@@ -98,19 +94,6 @@ export function LoginPage() {
|
||||
|
||||
return (
|
||||
<div className="min-h-dvh bg-morandi-50 flex items-center justify-center p-4 relative">
|
||||
{/* 调试浮层:点击可关闭 */}
|
||||
{debugInfo.length > 0 && (
|
||||
<div
|
||||
className="absolute top-0 left-0 right-0 z-50 bg-black/80 text-green-400 text-xs p-3 overflow-auto max-h-[50%] cursor-pointer font-mono"
|
||||
style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', lineHeight: 1.5 }}
|
||||
onClick={() => setDebugInfo([])}
|
||||
>
|
||||
<div style={{borderBottom:'1px solid #0f0',paddingBottom:4,marginBottom:4,fontWeight:'bold',fontSize:14}}>H5应用调试</div>
|
||||
{debugInfo.map((msg, i) => (
|
||||
<div key={i}>{msg}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-center">
|
||||
<motion.div
|
||||
animate={{ rotate: 360 }}
|
||||
|
||||
Reference in New Issue
Block a user