@@ -1111,6 +1111,27 @@ function setupShareFeature() {
11111111 const shareLinkInput = document . getElementById ( 'shareLinkInput' ) ;
11121112 const copyLinkBtn = document . getElementById ( 'copyLinkBtn' ) ;
11131113 const shareStatus = document . getElementById ( 'shareStatus' ) ;
1114+ const shareTurnstileContainer = document . getElementById ( 'shareTurnstileContainer' ) ;
1115+
1116+ // 彈窗開啟時立即渲染 Turnstile Widget
1117+ if ( typeof turnstile !== 'undefined' && shareTurnstileContainer ) {
1118+ ( async ( ) => {
1119+ try {
1120+ const siteKeyRes = await fetch ( '/api/turnstile-site-key' ) ;
1121+ const siteKeyData = await siteKeyRes . json ( ) ;
1122+ const siteKey = siteKeyData . siteKey ;
1123+ if ( siteKey ) {
1124+ const widgetId = turnstile . render ( shareTurnstileContainer , {
1125+ sitekey : siteKey ,
1126+ theme : 'dark' ,
1127+ } ) ;
1128+ shareTurnstileContainer . dataset . widgetId = widgetId ;
1129+ }
1130+ } catch ( e ) {
1131+ console . warn ( 'Failed to render share Turnstile:' , e ) ;
1132+ }
1133+ } ) ( ) ;
1134+ }
11141135
11151136 createLinkBtn . addEventListener ( 'click' , async ( ) => {
11161137 const gradesData = getStoredGrades ( ) ;
@@ -1120,50 +1141,21 @@ function setupShareFeature() {
11201141 return ;
11211142 }
11221143
1123- createLinkBtn . disabled = true ;
1124- createLinkBtn . textContent = '建立中...' ;
1125- shareStatus . textContent = '' ;
1126-
11271144 // 取得 Turnstile token
11281145 let turnstileResponse = '' ;
1129- if ( typeof turnstile !== 'undefined' ) {
1130- const shareTurnstileContainer = document . getElementById ( 'shareTurnstileContainer' ) ;
1131- if ( shareTurnstileContainer ) {
1132- // 渲染 widget (如果尚未渲染)
1133- if ( ! shareTurnstileContainer . dataset . widgetId ) {
1134- try {
1135- const siteKeyRes = await fetch ( '/api/turnstile-site-key' ) ;
1136- const siteKeyData = await siteKeyRes . json ( ) ;
1137- const siteKey = siteKeyData . siteKey ;
1138- if ( siteKey ) {
1139- const widgetId = turnstile . render ( shareTurnstileContainer , {
1140- sitekey : siteKey ,
1141- theme : 'dark' ,
1142- } ) ;
1143- shareTurnstileContainer . dataset . widgetId = widgetId ;
1144- // 等待用戶完成驗證
1145- createLinkBtn . disabled = false ;
1146- createLinkBtn . textContent = '建立分享連結' ;
1147- shareStatus . textContent = '請先完成人機驗證' ;
1148- shareStatus . className = 'status-msg' ;
1149- return ;
1150- }
1151- } catch ( e ) {
1152- console . warn ( 'Failed to render share Turnstile:' , e ) ;
1153- }
1154- } else {
1155- turnstileResponse = turnstile . getResponse ( shareTurnstileContainer . dataset . widgetId ) || '' ;
1156- if ( ! turnstileResponse ) {
1157- shareStatus . textContent = '請完成人機驗證' ;
1158- shareStatus . className = 'status-msg error' ;
1159- createLinkBtn . disabled = false ;
1160- createLinkBtn . textContent = '建立分享連結' ;
1161- return ;
1162- }
1163- }
1146+ if ( typeof turnstile !== 'undefined' && shareTurnstileContainer && shareTurnstileContainer . dataset . widgetId ) {
1147+ turnstileResponse = turnstile . getResponse ( shareTurnstileContainer . dataset . widgetId ) || '' ;
1148+ if ( ! turnstileResponse ) {
1149+ shareStatus . textContent = '請先完成人機驗證' ;
1150+ shareStatus . className = 'status-msg error' ;
1151+ return ;
11641152 }
11651153 }
11661154
1155+ createLinkBtn . disabled = true ;
1156+ createLinkBtn . textContent = '建立中...' ;
1157+ shareStatus . textContent = '' ;
1158+
11671159 try {
11681160 const payload = { ...gradesData , 'cf-turnstile-response' : turnstileResponse } ;
11691161 const res = await fetch ( '/api/share' , {
@@ -1178,6 +1170,8 @@ function setupShareFeature() {
11781170 shareLinkInput . value = link ;
11791171 linkContainer . style . display = 'block' ;
11801172 createLinkBtn . style . display = 'none' ;
1173+ // 隱藏 Turnstile
1174+ if ( shareTurnstileContainer ) shareTurnstileContainer . style . display = 'none' ;
11811175 shareStatus . textContent = '連結建立成功!' ;
11821176 shareStatus . className = 'status-msg success' ;
11831177 } else {
0 commit comments