From 13dd84a8a7cf201f937585d7221603aaa2c4daa5 Mon Sep 17 00:00:00 2001 From: zhongyingmin Date: Sun, 26 Oct 2025 13:15:41 +0800 Subject: [PATCH] feat: add avatar interaction and modal for user assistance - Introduced an avatar element that opens a modal when clicked, providing users with assistance. - Integrated IframeModal component to display external content within the modal. - Enhanced user experience with hover effects on the avatar. --- src/components/Modal.tsx | 143 +++++++++++++++++++++++++++++++++++++++ src/pages/Content.tsx | 32 +++++++++ 2 files changed, 175 insertions(+) create mode 100644 src/components/Modal.tsx diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx new file mode 100644 index 0000000..efbf44c --- /dev/null +++ b/src/components/Modal.tsx @@ -0,0 +1,143 @@ +import clsx from "clsx"; +import { useState } from "react"; + +interface ModalProps { + isOpen: boolean; + onClose: () => void; + children?: React.ReactNode; + className?: string; +} + +export const Modal = ({ isOpen, onClose, children, className }: ModalProps) => { + if (!isOpen) return null; + + return ( +
+ {/* 背景遮罩 */} +
+ + {/* 弹窗内容 */} +
+ {/* 关闭按钮 */} + + + {/* 弹窗内容 */} +
{children}
+
+
+ ); +}; + +interface IframeModalProps { + isOpen: boolean; + onClose: () => void; + url: string; + title?: string; +} + +export const IframeModal = ({ + isOpen, + onClose, + url, + title, +}: IframeModalProps) => { + const [hasError, setHasError] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [errorType, setErrorType] = useState< + "network" | "security" | "unknown" + >("unknown"); + + const handleIframeError = () => { + setHasError(true); + setIsLoading(false); + setErrorType("network"); + }; + + const handleIframeLoad = () => { + setIsLoading(false); + setHasError(false); + + // 监听iframe内部的错误 + const iframe = document.querySelector("iframe"); + if (iframe) { + try { + iframe.contentWindow?.addEventListener("error", (event) => { + console.error("Iframe内部错误:", event); + if ( + event.message?.includes("VideoDecoder") || + event.message?.includes("WebCodecs") + ) { + setErrorType("security"); + setHasError(true); + } + }); + } catch { + console.log("无法访问iframe内容,这是正常的跨域限制"); + } + } + }; + + return ( + +
+ {title && ( +
+

{title}

+
+ )} +
+ {isLoading && ( +
+
+
+

正在加载...

+
+
+ )} + + {hasError ? ( +
+
+
⚠️
+

+ {errorType === "security" ? "页面功能受限" : "页面加载失败"} +

+

+ {errorType === "security" + ? "该页面使用了高级视频处理功能,在嵌入模式下可能无法正常工作" + : "由于安全策略限制,无法在此窗口中显示该页面"} +

+

+ {errorType === "security" + ? "建议在支持的浏览器中直接访问该页面" + : "请检查网络连接或稍后重试"} +

+
+
+ ) : ( +