@@ -6,6 +6,9 @@ import useThrottle from "../components/hooks/useThrottle";
66import { setHtmlCodeUid } from '../components/compiler' ;
77import html2canvas from "html2canvas" ;
88import { HistoryContext } from '../components/contexts/HistoryContext' ;
9+ import {
10+ FaBug
11+ } from "react-icons/fa" ;
912
1013const editor = new Editor ( ) ;
1114globalContext . register ( editor , Editor ) ;
@@ -39,12 +42,21 @@ interface Props {
3942 appState : AppState ;
4043 sendMessageChange : ( e : any ) => void ;
4144 history : any ;
42- generatedCodeConfig : GeneratedCodeConfig
45+ generatedCodeConfig : GeneratedCodeConfig ,
46+ fixBug : ( error : {
47+ message : string ;
48+ stack : string ;
49+ } ) => void ;
4350}
4451
45- export default function PreviewBox ( { code, appState, sendMessageChange, history, generatedCodeConfig } : Props ) {
52+ export default function PreviewBox ( { code, appState, sendMessageChange, history, generatedCodeConfig, fixBug } : Props ) {
4653 const throttledCode = useThrottle ( code , 500 ) ;
4754 const { updateHistoryScreenshot} = useContext ( HistoryContext ) ;
55+ const [ showDebug , setShowDebug ] = useState < boolean > ( false ) ;
56+ const [ errorObj , setErrorObj ] = useState ( {
57+ message : '' ,
58+ stack : ''
59+ } ) ;
4860
4961 const onIframeLoad = async ( ) => {
5062 const img = await takeScreenshot ( ) ;
@@ -66,12 +78,45 @@ export default function PreviewBox({ code, appState, sendMessageChange, history,
6678 useEffect ( ( ) => {
6779 if ( appState === AppState . CODE_READY ) {
6880 const codeUid = setHtmlCodeUid ( generatedCodeConfig , code ) ;
69- designer . project . simulator ?. writeIframeDocument ( codeUid ) ;
81+ const errorIframe = `
82+ <script>
83+ window.addEventListener('error', (event) => {
84+ window.parent.postMessage({
85+ message: event.message,
86+ error: event.error
87+ }, '*')
88+ })
89+ </script>
90+ ` ;
91+ let content = '' ;
92+ var patternHead = / < t i t l e [ ^ > ] * > ( ( .| [ \n \r ] ) * ) < \/ t i t l e > / im; //匹配header
93+ const headMatch = codeUid . match ( patternHead ) ;
94+ if ( headMatch ) {
95+ const headContent = headMatch [ 0 ] + errorIframe ;
96+ content = codeUid . replace ( patternHead , headContent ) ;
97+ }
98+ designer . project . simulator ?. writeIframeDocument ( content || codeUid ) ;
7099 } else {
71100 // designer.project.simulator?.writeIframeDocument(throttledCode);
72101 }
73102 } , [ code , appState ] ) ;
74103
104+ useEffect ( ( ) => {
105+ const messageHandler = ( e : any ) => {
106+ if ( e . data && e . data . error ) {
107+ setErrorObj ( {
108+ message : e . data . error . message ,
109+ stack : e . data . error . stack
110+ } ) ;
111+ setShowDebug ( true ) ;
112+ }
113+ }
114+ window . addEventListener ( 'message' , messageHandler ) ;
115+ return ( ) => {
116+ window . removeEventListener ( 'message' , messageHandler ) ;
117+ }
118+ } , [ ] )
119+
75120 const takeScreenshot = async ( ) : Promise < string > => {
76121 const body = designer . project . simulator ?. contentWindow ?. document . body ;
77122 if ( ! body ) {
@@ -85,6 +130,17 @@ export default function PreviewBox({ code, appState, sendMessageChange, history,
85130
86131 return (
87132 < div className = "border-[4px] border-black rounded-[20px] shadow-lg w-full h-full" >
133+ {
134+ showDebug && (
135+ < span
136+ onClick = { ( ) => {
137+ fixBug ( errorObj ) ;
138+ } }
139+ className = 'text-red-600 absolute right-14 top-16 z-[50] hover:bg-slate-200 rounded-sm p-2' >
140+ < FaBug />
141+ </ span >
142+ )
143+ }
88144 < DesignerView
89145 editor = { editor }
90146 designer = { editor . get ( 'designer' ) }
0 commit comments