@@ -225,13 +225,13 @@ function App() {
225225 try {
226226 const uuid = searchParams . get ( "uuid" ) ;
227227 const fid = searchParams . get ( "file" ) ;
228- let info : ScriptInfo | undefined ;
229- let isKnownUpdate : boolean = false ;
230228
231- // 如果没有 uuid 和 file,跳过初始化逻辑
232- if ( ! uuid && ! fid ) {
229+ // 如果有 url 或 没有 uuid 和 file,跳过初始化逻辑
230+ if ( searchParams . get ( "url" ) || ( ! uuid && ! fid ) ) {
233231 return ;
234232 }
233+ let info : ScriptInfo | undefined ;
234+ let isKnownUpdate : boolean = false ;
235235
236236 if ( window . history . length > 1 ) {
237237 setDoBackwards ( true ) ;
@@ -649,84 +649,107 @@ function App() {
649649 } , [ memoWatchFile ] ) ;
650650
651651 // 检查是否有 uuid 或 file
652- const hasUUIDorFile = useMemo ( ( ) => {
653- return ! ! ( searchParams . get ( "uuid" ) || searchParams . get ( "file" ) ) ;
654- } , [ searchParams ] ) ;
652+ const searchParamUrl = searchParams . get ( "url" ) ;
653+ const hasValidSourceParam = ! searchParamUrl && ! ! ( searchParams . get ( "uuid" ) || searchParams . get ( "file" ) ) ;
655654
656655 const urlHref = useMemo ( ( ) => {
657- try {
658- if ( ! hasUUIDorFile ) {
659- const url = searchParams . get ( "url" ) ;
660- if ( url ) {
661- const urlObject = new URL ( url ) ;
656+ if ( ! hasValidSourceParam ) {
657+ let rawUrl ;
658+ try {
659+ // 取url=之后的所有内容
660+ rawUrl = location . search . match ( / \? u r l = ( [ ^ & ] + ) / ) ?. [ 1 ] || "" ;
661+ if ( rawUrl ) {
662+ const urlObject = new URL ( rawUrl ) ;
663+ // 验证解析后的 URL 是否具备核心要素,确保安全性与合法性
662664 if ( urlObject . protocol && urlObject . hostname && urlObject . pathname ) {
663- return urlObject . href ;
665+ return rawUrl ;
664666 }
665667 }
668+ } catch {
669+ // ignored
666670 }
667- } catch {
668- // ignored
669671 }
670672 return "" ;
671- } , [ hasUUIDorFile , searchParams ] ) ;
673+ } , [ hasValidSourceParam ] ) ;
672674
673675 const [ fetchingState , setFetchingState ] = useState ( {
674676 loadingStatus : "" ,
675677 errorStatus : "" ,
676678 } ) ;
677679
678- const loadURLAsync = async ( urlHref : string ) => {
679- try {
680- const { code, metadata } = await fetchScriptBody ( urlHref , {
680+ const loadURLAsync = async ( url : string ) => {
681+ // 1. 定义获取单个脚本的内部逻辑,负责处理进度条与单次错误
682+ const fetchValidScript = async ( ) => {
683+ const result = await fetchScriptBody ( url , {
681684 onProgress : ( info : { receivedLength : number } ) => {
682685 setFetchingState ( ( prev ) => ( {
683686 ...prev ,
684- loadingStatus : t ( "downloading_status_text" , { bytes : ` ${ formatBytes ( info . receivedLength ) } ` } ) ,
687+ loadingStatus : t ( "downloading_status_text" , { bytes : formatBytes ( info . receivedLength ) } ) ,
685688 } ) ) ;
686689 } ,
687690 } ) ;
688- const update = false ;
691+ if ( result . code && result . metadata ) {
692+ return { result, url } as const ; // 找到有效的立即返回
693+ }
694+ throw new Error ( t ( "install_page_load_failed" ) ) ;
695+ } ;
696+
697+ try {
698+ // 2. 执行获取
699+ const { result, url } = await fetchValidScript ( ) ;
700+ const { code, metadata } = result ;
701+
702+ // 3. 处理数据与缓存
689703 const uuid = uuidv4 ( ) ;
690- const url = urlHref ;
691- const upsertBy = "user" ;
692-
693- const si = [ update , createScriptInfo ( uuid , code , url , upsertBy , metadata ) ] ;
694- await cacheInstance . set ( `${ CACHE_KEY_SCRIPT_INFO } ${ uuid } ` , si ) ;
695- setSearchParams (
696- ( prev ) => {
697- prev . delete ( "url" ) ;
698- prev . set ( "uuid" , uuid ) ;
699- return prev ;
700- } ,
701- { replace : true }
702- ) ;
704+ const scriptData = [ false , createScriptInfo ( uuid , code , url , "user" , metadata ) ] ;
705+
706+ await cacheInstance . set ( `${ CACHE_KEY_SCRIPT_INFO } ${ uuid } ` , scriptData ) ;
707+
708+ // 4. 更新导向
709+ setSearchParams ( new URLSearchParams ( `?uuid=${ uuid } ` ) , { replace : true } ) ;
703710 } catch ( err : any ) {
704- const errMessage = ` ${ err . message || err } ` ;
711+ // 5. 统一错误处理
705712 setFetchingState ( ( prev ) => ( {
706713 ...prev ,
707714 loadingStatus : "" ,
708- errorStatus : errMessage ,
715+ errorStatus : ` ${ err ?. message || err } ` ,
709716 } ) ) ;
710717 }
711718 } ;
712719
720+ const handleUrlChangeAndFetch = ( targetUrlHref : string ) => {
721+ setFetchingState ( ( prev ) => ( {
722+ ...prev ,
723+ loadingStatus : t ( "install_page_please_wait" ) ,
724+ } ) ) ;
725+ loadURLAsync ( targetUrlHref ) ;
726+ } ;
727+
728+ // 有 url 的话下载内容
713729 useEffect ( ( ) => {
714- if ( ! urlHref ) return ;
715- loadURLAsync ( urlHref ) ;
730+ if ( urlHref ) handleUrlChangeAndFetch ( urlHref ) ;
731+ // eslint-disable-next-line react-hooks/exhaustive-deps
716732 } , [ urlHref ] ) ;
717733
718- if ( ! hasUUIDorFile ) {
734+ if ( ! hasValidSourceParam ) {
719735 return urlHref ? (
720736 < div className = "tw-flex tw-justify-center tw-items-center tw-h-screen" >
721737 < Space direction = "vertical" align = "center" >
722- < Typography . Title heading = { 3 } > { t ( "install_page_loading" ) } </ Typography . Title >
723738 { fetchingState . loadingStatus && (
724- < div className = "downloading" >
725- < Typography . Text > { fetchingState . loadingStatus } </ Typography . Text >
726- < div className = "loader" > </ div >
727- </ div >
739+ < >
740+ < Typography . Title heading = { 3 } > { t ( "install_page_loading" ) } </ Typography . Title >
741+ < div className = "downloading" >
742+ < Typography . Text > { fetchingState . loadingStatus } </ Typography . Text >
743+ < div className = "loader" > </ div >
744+ </ div >
745+ </ >
746+ ) }
747+ { fetchingState . errorStatus && (
748+ < >
749+ < Typography . Title heading = { 3 } > { t ( "install_page_load_failed" ) } </ Typography . Title >
750+ < div className = "error-message" > { fetchingState . errorStatus } </ div >
751+ </ >
728752 ) }
729- { fetchingState . errorStatus && < div className = "error-message" > { fetchingState . errorStatus } </ div > }
730753 </ Space >
731754 </ div >
732755 ) : (
0 commit comments