@@ -4,11 +4,15 @@ let barChartInstance = null;
44
55// 全域 Turnstile 管理器
66const GlobalTurnstileManager = {
7- widgetId : null ,
7+ widgetIds : { } ,
88 isEnabled : true ,
99 siteKey : null ,
10+ initPromise : null ,
1011
1112 async init ( ) {
13+ if ( this . initPromise ) return this . initPromise ;
14+
15+ this . initPromise = ( async ( ) => {
1216 try {
1317 const res = await fetch ( '/api/turnstile-site-key' ) ;
1418 const data = await res . json ( ) ;
@@ -20,9 +24,14 @@ const GlobalTurnstileManager = {
2024 console . warn ( 'Failed to init global Turnstile:' , e ) ;
2125 this . isEnabled = false ;
2226 }
27+ } ) ( ) ;
28+
29+ return this . initPromise ;
2330 } ,
2431
2532 async render ( containerId ) {
33+ await this . init ( ) ;
34+
2635 if ( ! this . isEnabled || ! this . siteKey ) return ;
2736
2837 try {
@@ -41,13 +50,13 @@ const GlobalTurnstileManager = {
4150 const container = document . getElementById ( containerId ) ;
4251 if ( ! container ) return ;
4352
44- if ( this . widgetId !== null ) {
45- turnstile . remove ( this . widgetId ) ;
53+ if ( this . widgetIds [ containerId ] !== undefined ) {
54+ turnstile . remove ( this . widgetIds [ containerId ] ) ;
4655 }
4756
4857 container . innerHTML = '' ;
4958
50- this . widgetId = turnstile . render ( container , {
59+ this . widgetIds [ containerId ] = turnstile . render ( container , {
5160 sitekey : this . siteKey ,
5261 theme : 'dark'
5362 } ) ;
@@ -56,18 +65,20 @@ const GlobalTurnstileManager = {
5665 }
5766 } ,
5867
59- getToken ( ) {
68+ getToken ( containerId ) {
6069 if ( ! this . isEnabled ) return 'disabled' ;
61- if ( typeof turnstile !== 'undefined' && this . widgetId !== null ) {
62- return turnstile . getResponse ( this . widgetId ) || '' ;
70+ const widgetId = this . widgetIds [ containerId ] ;
71+ if ( typeof turnstile !== 'undefined' && widgetId !== undefined ) {
72+ return turnstile . getResponse ( widgetId ) || '' ;
6373 }
6474 return '' ;
6575 } ,
6676
67- reset ( ) {
77+ reset ( containerId ) {
6878 if ( ! this . isEnabled ) return ;
69- if ( typeof turnstile !== 'undefined' && this . widgetId !== null ) {
70- turnstile . reset ( this . widgetId ) ;
79+ const widgetId = this . widgetIds [ containerId ] ;
80+ if ( typeof turnstile !== 'undefined' && widgetId !== undefined ) {
81+ turnstile . reset ( widgetId ) ;
7182 }
7283 }
7384} ;
@@ -776,7 +787,7 @@ function setupSyncFeature() {
776787 }
777788
778789 // 取得 Turnstile token
779- const turnstileResponse = GlobalTurnstileManager . getToken ( ) ;
790+ const turnstileResponse = GlobalTurnstileManager . getToken ( 'loginTurnstileContainer' ) ;
780791 if ( ! turnstileResponse ) {
781792 showStatus ( loginStatus , '請稍候,系統安全驗證處理中...' , 'error' ) ;
782793 return ;
@@ -804,11 +815,11 @@ function setupSyncFeature() {
804815 } , 500 ) ;
805816 } else {
806817 showStatus ( loginStatus , data . message || '登入失敗' , 'error' ) ;
807- GlobalTurnstileManager . reset ( ) ;
818+ GlobalTurnstileManager . reset ( 'loginTurnstileContainer' ) ;
808819 }
809820 } catch ( error ) {
810821 showStatus ( loginStatus , '連線錯誤: ' + error . message , 'error' ) ;
811- GlobalTurnstileManager . reset ( ) ;
822+ GlobalTurnstileManager . reset ( 'loginTurnstileContainer' ) ;
812823 } finally {
813824 confirmLogin . disabled = false ;
814825 }
@@ -1044,7 +1055,7 @@ function setupShareFeature() {
10441055 }
10451056
10461057 // 取得 Turnstile token
1047- const turnstileResponse = GlobalTurnstileManager . getToken ( ) ;
1058+ const turnstileResponse = GlobalTurnstileManager . getToken ( 'shareTurnstileContainer' ) ;
10481059 if ( ! turnstileResponse ) {
10491060 shareStatus . textContent = '請稍候,系統安全驗證處理中...' ;
10501061 shareStatus . className = 'status-msg error' ;
@@ -1080,7 +1091,7 @@ function setupShareFeature() {
10801091 shareStatus . className = 'status-msg error' ;
10811092 createLinkBtn . disabled = false ;
10821093 createLinkBtn . textContent = '建立分享連結' ;
1083- GlobalTurnstileManager . reset ( ) ;
1094+ GlobalTurnstileManager . reset ( 'shareTurnstileContainer' ) ;
10841095 }
10851096 } ) ;
10861097
0 commit comments