PageSourceSearch

https://www.crysound.com/wp-content/plugins/casdoor-member-system%205/assets/js/script-en.js?ver=1789875818

js crysound.com collected 2026-10-02 14:42:27 UTC 61,553 bytes, 1,419 lines download raw bytes

1function showMessage(type, message, persistent) {
2    persistent = persistent || false;
3    jQuery('.casdoor-top-notification').remove();
4    
5    var icon = '';
6    if (type === 'success') {
7        icon = '<svg class="casdoor-notification-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m265.9 713.9a377.2 377.2 0 0 1-119.6 80.6 377.5 377.5 0 0 1-292.6 0 377.1 377.1 0 0 1-200.2-200.2 377.5 377.5 0 0 1 0-292.6 377.1 377.1 0 0 1 200.2-200.2 377.5 377.5 0 0 1 292.6 0 377.1 377.1 0 0 1 200.2 200.2 377.5 377.5 0 0 1 0 292.6 377.2 377.2 0 0 1-80.6 119.6z m-66.8-448.7a4 4 0 0 0-5.7 0l-264.5 264a3.9 3.9 0 0 1-5.6 0L318.6 476.7a4.2 4.2 0 0 0-5.7 0l-45.2 45.2a3.9 3.9 0 0 0 0 5.6l167.6 167.3a3.9 3.9 0 0 0 5.6 0L756.3 380a4 4 0 0 0 0-5.7z" fill="#22C55E"></path></svg>';
8    } else if (type === 'error') {
9        icon = '<svg class="casdoor-notification-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 947.2C271.36 947.2 76.8 752.64 76.8 512S271.36 76.8 512 76.8 947.2 271.36 947.2 512 752.64 947.2 512 947.2M512 0C230.4 0 0 230.4 0 512s230.4 512 512 512 512-230.4 512-512S793.6 0 512 0" fill="#d81e06"></path><path d="M716.8 353.28l-61.44-46.08L512 455.68 368.64 307.2l-61.44 46.08L455.68 512 307.2 665.6l61.44 51.2L512 568.32 655.36 716.8l61.44-51.2L563.2 512z" fill="#d81e06"></path></svg>';
10    }
11    
12    var notification = jQuery('<div class="casdoor-top-notification ' + type + '">' + icon + message + '</div>');
13    jQuery('body').append(notification);
14    if (!persistent) {
15        setTimeout(function() {
16            notification.fadeOut(300, function() {
17                jQuery(this).remove();
18            });
19        }, 3500);
20    }
21}
22
23function getUrlParameter(name) {
24    var results = new RegExp('[?&]' + name + '=([^&#]*)').exec(window.location.href);
25    if (results == null) {
26        return null;
27    }
28    return results[1] || null;
29}
30
31function casdoorT(key, fallback) {
32    if (
33        typeof casdoor_ajax !== 'undefined' &&
34        casdoor_ajax.i18n &&
35        Object.prototype.hasOwnProperty.call(casdoor_ajax.i18n, key)
36    ) {
37        return casdoor_ajax.i18n[key];
38    }
39    return fallback;
40}
41
42function casdoorFormat(message) {
43    var args = Array.prototype.slice.call(arguments, 1);
44    args.forEach(function(value) {
45        message = message.replace('%s', value);
46    });
47    return message;
48}
49
50function cleanupTransientUrlParams() {
51    try {
52        var url = new URL(window.location.href);
53        var changed = false;
54
55        ['casdoor_login_refresh'].forEach(function(param) {
56            if (url.searchParams.has(param)) {
57                url.searchParams.delete(param);
58                changed = true;
59            }
60        });
61
62        if (changed && window.history && window.history.replaceState) {
63            var cleanUrl = url.pathname + (url.search ? url.search : '') + url.hash;
64            window.history.replaceState({}, document.title, cleanUrl);
65        }
66    } catch (e) {
67        // ignore URL cleanup issues
68    }
69}
70
71jQuery(document).ready(function($) {
72    'use strict';
73
74    cleanupTransientUrlParams();
75    
76    // 改进的初始化检查,提供更详细的错误信息
77    if (typeof casdoor_ajax === 'undefined') {
78        console.error('❌ Casdoor Ajax object not loaded! This will cause 403 errors.');
79        console.log('Possible causes:');
80        console.log('1. WP Rocket cached the old page without nonce');
81        console.log('2. CDN cached the page');
82        console.log('3. Script not enqueued properly');
83        
84        // 尝试从内联脚本获取 nonce (降级方案)
85        var inlineNonce = $('input[name="casdoor_nonce"]').val();
86        if (inlineNonce) {
87            console.log('✅ Found inline nonce, using fallback mode');
88            window.casdoor_ajax = {
89                ajax_url: '/wp-admin/admin-ajax.php',
90                nonce: inlineNonce,
91                home_url: window.location.origin
92            };
93        } else {
94            showMessage('error', casdoorT('pageInitializationError', 'Page initialization error. Please clear your browser cache and refresh.'));
95            return;
96        }
97    }
98    
99    // 同样检查 upc_ajax
100    if (typeof upc_ajax === 'undefined') {
101        var upcNonce = $('input[name="upc_nonce"]').val();
102        if (upcNonce) {
103            window.upc_ajax = {
104                ajax_url: '/wp-admin/admin-ajax.php',
105                nonce: upcNonce
106            };
107        }
108    }
109
110    function getAjaxUrl() {
111        if (typeof casdoor_ajax !== 'undefined' && casdoor_ajax.ajax_url) {
112            return casdoor_ajax.ajax_url;
113        }
114        if (typeof upc_ajax !== 'undefined' && upc_ajax.ajax_url) {
115            return upc_ajax.ajax_url;
116        }
117        return '/wp-admin/admin-ajax.php';
118    }
119
120    function updateFrontendBootstrap(data) {
121        if (!data) {
122            return;
123        }
124
125        if (data.nonces) {
126            if (typeof casdoor_ajax !== "undefined" && data.nonces.casdoor) {
127                casdoor_ajax.nonce = data.nonces.casdoor;
128            }
129            if (typeof upc_ajax !== "undefined" && data.nonces.upc) {
130                upc_ajax.nonce = data.nonces.upc;
131            }
132
133            if (data.nonces.casdoor) {
134                $("input[name=\"casdoor_nonce\"]").val(data.nonces.casdoor);
135            }
136            if (data.nonces.upc) {
137                $("input[name=\"upc_nonce\"]").val(data.nonces.upc);
138            }
139        }
140
141        if (typeof casdoor_ajax !== "undefined" && data.urls) {
142            casdoor_ajax.urls = $.extend({}, casdoor_ajax.urls || {}, data.urls);
143        }
144
145        if (data.logged_in && data.user) {
146            normalizeLoggedInHeaderState(data.user, data.urls || (typeof casdoor_ajax !== "undefined" ? casdoor_ajax.urls : {}));
147        }
148    }
149
150    function currentPageLooksLikeAuthPage() {
151        return $("#casdoor-login-form").length > 0 ||
152            $("#casdoor-register-step1-form").length > 0 ||
153            $("#casdoor-forgot-password-form").length > 0 ||
154            $("#casdoor-reset-password-form").length > 0;
155    }
156
157    function pageShowsGuestHeaderState() {
158        var desktopGuest = $(".ct-header-account[data-id=\"account\"][data-state=\"out\"] a[href*=\"/login\"]").length > 0;
159        var mobileGuest = $(".elementor-widget-button.login a[href*=\"/login\"]").length > 0;
160        return desktopGuest || mobileGuest;
161    }
162
163    function escapeHtml(value) {
164        return String(value || "")
165            .replace(/&/g, "&amp;")
166            .replace(/</g, "&lt;")
167            .replace(/>/g, "&gt;")
168            .replace(/"/g, "&quot;")
169            .replace(/\x27/g, "&#039;");
170    }
171
172    function getAccountUrl(urls) {
173        return (urls && urls.account) ||
174            (typeof casdoor_ajax !== "undefined" && casdoor_ajax.urls && casdoor_ajax.urls.account) ||
175            "/account";
176    }
177
178    function getAccountDisplayName(user, $headerAccount) {
179        var currentLabel = $headerAccount && $headerAccount.length ? $.trim($headerAccount.find(".ct-account-item .ct-label").first().text()) : "";
180        return (user && (user.display_name || user.name || user.email)) || currentLabel || "My Account";
181    }
182
183    function normalizeAccountMenuLinks($headerAccount, accountUrl) {
184        if (!$headerAccount.length || !accountUrl) {
185            return;
186        }
187
188        $headerAccount.find(".ct-header-account-dropdown a[href], .ct-header-account-content-block a[href]").each(function() {
189            var $link = $(this);
190            var href = String($link.attr("href") || "");
191            var text = $.trim($link.text());
192
193            if ($link.attr("id") === "np_logout_url" || href.charAt(0) === "#" || /^mailto:|^tel:/i.test(href)) {
194                return;
195            }
196
197            if (
198                $link.closest(".ct-header-account-content-block").length ||
199                /\/account(?:-|\/|$)|\/my-account(?:\/|$)/i.test(href) ||
200                /^(My Account|マイアカウント|我的账户|Mon compte|Mi cuenta)$/i.test(text)
201            ) {
202                $link.attr("href", accountUrl);
203            }
204        });
205    }
206
207    function normalizeLoggedInHeaderState(user, urls) {
208        var $headerAccounts = $(".ct-header-account[data-id=\"account\"][data-state=\"in\"]");
209        if (!$headerAccounts.length || !user) {
210            return false;
211        }
212
213        var accountUrl = getAccountUrl(urls);
214        $headerAccounts.each(function() {
215            var $headerAccount = $(this);
216            var displayName = getAccountDisplayName(user, $headerAccount);
217
218            $headerAccount.removeAttr("data-label");
219            $headerAccount.find(".ct-account-item .ct-label").first().text(displayName);
220            normalizeAccountMenuLinks($headerAccount, accountUrl);
221        });
222
223        return true;
224    }
225
226    function updateGuestHeaderState(user, urls, accountMenuHtml) {
227        var $headerAccount = $(".ct-header-account[data-id=\"account\"][data-state=\"out\"]");
228        if (!$headerAccount.length || !user) {
229            return false;
230        }
231
232        var accountUrl = getAccountUrl(urls);
233        var displayName = getAccountDisplayName(user, $headerAccount);
234        var safeDisplayName = escapeHtml(displayName);
235        var iconMarkup = $headerAccount.find(".ct-icon").first().prop("outerHTML") || "";
236        var hasRichDropdown = typeof accountMenuHtml === "string" && accountMenuHtml.indexOf("ct-header-account-content-block") !== -1;
237
238        $headerAccount.attr("data-state", "in");
239        $headerAccount.removeAttr("data-label");
240        $headerAccount.find("a.ct-account-item").first().replaceWith(
241            "<span class=\"ct-account-item\" data-label=\"right\" tabindex=\"0\">" +
242                "<span class=\"ct-label ct-hidden-sm ct-hidden-md\" aria-hidden=\"true\">" + safeDisplayName + "</span>" +
243                iconMarkup +
244            "</span>"
245        );
246
247        if (hasRichDropdown) {
248            $headerAccount.find(".ct-header-account-dropdown, .ct-header-account-content-block").remove();
249            $headerAccount.append(accountMenuHtml);
250            normalizeLoggedInHeaderState(user, urls);
251            return true;
252        }
253
254        if (!$headerAccount.find(".ct-header-account-dropdown").length) {
255            $headerAccount.append(
256                "<ul class=\"ct-header-account-dropdown\" data-dropdown=\"type-1:simple\" data-placement=\"left\">" +
257                    "<li><a href=\"" + escapeHtml(accountUrl) + "\">My Account</a></li>" +
258                "</ul>"
259            );
260        }
261
262        normalizeLoggedInHeaderState(user, urls);
263        return true;
264    }
265
266    function maybeRefreshGuestHeader(loggedIn) {
267        var refreshKey = 'casdoor_header_refresh_' + window.location.pathname;
268
269        if (!loggedIn) {
270            try {
271                sessionStorage.removeItem(refreshKey);
272            } catch (e) {
273                // ignore storage errors
274            }
275            return;
276        }
277
278        if (currentPageLooksLikeAuthPage()) {
279            return;
280        }
281
282        if (!pageShowsGuestHeaderState()) {
283            try {
284                sessionStorage.removeItem(refreshKey);
285            } catch (e) {
286                // ignore storage errors
287            }
288            return;
289        }
290
291        try {
292            if (sessionStorage.getItem(refreshKey) === '1') {
293                return;
294            }
295            sessionStorage.setItem(refreshKey, '1');
296        } catch (e) {
297            // ignore storage errors and still attempt one refresh
298        }
299
300        window.location.reload();
301    }
302
303    function buildReferrerRedirect() {
304        if (!document.referrer) {
305            return '';
306        }
307
308        try {
309            var referrerUrl = new URL(document.referrer, window.location.origin);
310            var currentUrl = new URL(window.location.href, window.location.origin);
311
312            if (referrerUrl.origin !== window.location.origin) {
313                return '';
314            }
315
316            if (referrerUrl.href === currentUrl.href) {
317                return '';
318            }
319
320            var authPaths = [
321                '/login',
322                '/register',
323                '/forgot-password',
324                '/reset-password',
325                '/account',
326                '/user-center'
327            ];
328
329            for (var i = 0; i < authPaths.length; i++) {
330                if (referrerUrl.pathname.indexOf(authPaths[i]) !== -1) {
331                    return '';
332                }
333            }
334
335            return referrerUrl.href;
336        } catch (e) {
337            return '';
338        }
339    }
340
341    function refreshFrontendBootstrap() {
342        return $.ajax({
343            url: getAjaxUrl(),
344            type: 'POST',
345            cache: false,
346            data: {
347                action: 'casdoor_frontend_bootstrap'
348            }
349        }).done(function(response) {
350            if (!response || !response.success || !response.data) {
351                return;
352            }
353
354            updateFrontendBootstrap(response.data);
355
356            if (response.data.logged_in && currentPageLooksLikeAuthPage()) {
357                var accountUrl = (response.data.urls && response.data.urls.account) ||
358                    ((typeof casdoor_ajax !== 'undefined' && casdoor_ajax.urls && casdoor_ajax.urls.account) ? casdoor_ajax.urls.account : '/account');
359                window.location.replace(accountUrl);
360                return;
361            }
362
363            if (response.data.logged_in) {
364                updateGuestHeaderState(response.data.user, response.data.urls, response.data.account_menu_html);
365            }
366
367            maybeRefreshGuestHeader(response.data.logged_in);
368        });
369    }
370
371    function buildFreshRedirectUrl(url) {
372        if (!url) {
373            return url;
374        }
375
376        try {
377            var targetUrl = new URL(url, window.location.origin);
378            if (targetUrl.origin === window.location.origin) {
379                targetUrl.searchParams.set('casdoor_login_refresh', String(Date.now()));
380                return targetUrl.toString();
381            }
382        } catch (e) {
383            // ignore parse errors and fall back to the original URL
384        }
385
386        return url;
387    }
388
389    function sendLoginRequest(payload, submitBtn, submitText, hasRetriedAfterNonceRefresh) {
390        $.ajax({
391            url: getAjaxUrl(),
392            type: 'POST',
393            cache: false,
394            data: payload,
395            success: function(response) {
396                if (response.success) {
397                    showMessage('success', response.message);
398                    if (response.redirect_url) {
399                        if (response.redirect_url.indexOf('/account') > -1 ||
400                            response.redirect_url.indexOf('/profile') > -1) {
401                            try {
402                                if (typeof sessionStorage !== 'undefined') {
403                                    sessionStorage.setItem('upc_from_login', 'true');
404                                }
405                            } catch(e) {
406                                // sessionStorage不可用,忽略错误
407                            }
408                        }
409                        setTimeout(function() {
410                            window.location.replace(buildFreshRedirectUrl(response.redirect_url));
411                        }, 500);
412                    }
413                    return;
414                }
415
416                if (!hasRetriedAfterNonceRefresh &&
417                    response &&
418                    typeof response.message === 'string' &&
419                    response.message.indexOf('Security verification failed') !== -1) {
420                    refreshFrontendBootstrap()
421                        .done(function() {
422                            payload.nonce = (typeof casdoor_ajax !== 'undefined' && casdoor_ajax.nonce) ? casdoor_ajax.nonce : payload.nonce;
423                            sendLoginRequest(payload, submitBtn, submitText, true);
424                        })
425                        .fail(function() {
426                            showMessage('error', response.message);
427                            submitBtn.prop('disabled', false);
428                            submitText.text(casdoorT('logIn', 'Log In'));
429                        });
430                    return;
431                }
432
433                showMessage('error', response.message);
434                submitBtn.prop('disabled', false);
435                submitText.text(casdoorT('logIn', 'Log In'));
436            },
437            error: function() {
438                showMessage('error', casdoorT('networkErrorTryAgain', 'Network error. Please try again.'));
439                submitBtn.prop('disabled', false);
440                submitText.text(casdoorT('logIn', 'Log In'));
441            }
442        });
443    }
444
445    refreshFrontendBootstrap();
446    
447    $(document).on('submit', '#casdoor-login-form', function(e) {
448        e.preventDefault();
449        e.stopPropagation();
450        
451        $('.casdoor-top-notification').remove();
452        
453        var form = $(this);
454        var submitBtn = form.find('.casdoor-auth-login-button');
455        var submitText = submitBtn.find('.casdoor-login-text');
456        var accountInput = form.find('#casdoor-account');
457        var passwordInput = form.find('#casdoor-password');
458        var account = accountInput.length ? (accountInput.val() ? accountInput.val().trim() : '') : '';
459        var password = passwordInput.length ? (passwordInput.val() || '') : '';
460        
461        if (!account || !password) {
462            showMessage('error', casdoorT('enterAccountAndPassword', 'Please enter both account and password.'));
463            return;
464        }
465        
466        submitBtn.prop('disabled', true);
467        submitText.text(casdoorT('signingIn', 'Signing in...'));
468        
469
470        // Only honor an explicit redirect_to in the login URL.
471        // Falling back to document.referrer can send users back to a cached
472        // guest page, which makes a successful login look like it failed.
473        var redirectTo = '';
474        var urlRedirect = getUrlParameter('redirect_to');
475        if (urlRedirect) {
476            redirectTo = decodeURIComponent(urlRedirect);
477        } else {
478            redirectTo = buildReferrerRedirect();
479        }
480
481        var payload = {
482            action: 'casdoor_login',
483            account: account,
484            password: password,
485            redirect_to: redirectTo,
486            current_url: window.location.href,
487            language_code: (typeof casdoor_ajax !== 'undefined' && casdoor_ajax.language_code) ? casdoor_ajax.language_code : '',
488            locale: (typeof casdoor_ajax !== 'undefined' && casdoor_ajax.locale) ? casdoor_ajax.locale : '',
489            nonce: (typeof casdoor_ajax !== 'undefined' && casdoor_ajax.nonce) ? casdoor_ajax.nonce : ''
490        };
491
492        refreshFrontendBootstrap()
493            .always(function() {
494                payload.nonce = (typeof casdoor_ajax !== 'undefined' && casdoor_ajax.nonce) ? casdoor_ajax.nonce : payload.nonce;
495                sendLoginRequest(payload, submitBtn, submitText, false);
496            });
497    });
498    
499    $(document).on('submit', '#casdoor-register-step1-form', function(e) {
500        e.preventDefault();
501        e.stopPropagation();
502        
503        var form = $(this);
504        var submitBtn = form.find('.casdoor-auth-login-button');
505        var submitText = submitBtn.find('.casdoor-login-text');
506        var emailInput = form.find('#casdoor-email');
507        var email = emailInput.length ? (emailInput.val() ? emailInput.val().trim() : '') : '';
508        var privacyCheckbox = form.find('input[name="privacy_agree"]');
509        var privacyAgree = privacyCheckbox.length ? privacyCheckbox.is(':checked') : false;
510        
511        if (!email) {
512            showMessage('error', casdoorT('enterEmailAddress', 'Please enter your email address.'));
513            return;
514        }
515        
516        if (!privacyAgree) {
517            showMessage('error', casdoorT('agreePrivacyTerms', 'Please agree to the Privacy Policy and Terms of Use.'));
518            return;
519        }
520        
521        submitBtn.prop('disabled', true);
522        var originalButtonHtml = submitBtn.html();
523        submitText.text(casdoorT('sending', 'Sending...'));
524        
525        $.ajax({
526            url: casdoor_ajax.ajax_url,
527            type: 'POST',
528            data: {
529                action: 'casdoor_register_step1',
530                email: email,
531                current_url: window.location.href,
532                redirect_to: form.find('input[name="redirect_to"]').val() || '',
533                language_code: casdoor_ajax.language_code || '',
534                locale: casdoor_ajax.locale || '',
535                nonce: casdoor_ajax.nonce
536            },
537            timeout: 30000,
538            success: function(response) {
539                if (response.success) {
540                    showMessage('success', casdoorT('emailSent', 'Email sent'));
541                    startEmailCooldown(submitBtn, submitText, 60, originalButtonHtml);
542                } else {
543                    var errorMessage = (response.data && response.data.message) ? response.data.message : (response.message || casdoorT('registrationFailedTryAgain', 'Registration failed. Please try again.'));
544                    showMessage('error', errorMessage);
545                    submitBtn.prop('disabled', false).html(originalButtonHtml);
546                }
547            },
548            error: function(xhr, status, error) {
549                var errorMsg = casdoorT('networkErrorTryAgain', 'Network error. Please try again.');
550                if (status === 'timeout') {
551                    errorMsg = casdoorT('requestTimeoutCheckConnection', 'Request timeout. Please check your connection and try again.');
552                } else if (xhr.responseText) {
553                    try {
554                        var resp = JSON.parse(xhr.responseText);
555                        errorMsg = (resp.data && resp.data.message) ? resp.data.message : (resp.message || errorMsg);
556                    } catch (e) {
557                    }
558                }
559                showMessage('error', errorMsg);
560                submitBtn.prop('disabled', false).html(originalButtonHtml);
561            }
562        });
563    });
564    
565    function startEmailCooldown(button, textElement, seconds, originalHtml) {
566        var remainingTime = seconds;
567        
568        function updateButton() {
569            if (remainingTime > 0) {
570                button.prop('disabled', true);
571                textElement.text(casdoorFormat(casdoorT('resendCountdown', 'Resend (%ss)'), remainingTime));
572                remainingTime--;
573                setTimeout(updateButton, 1000);
574            } else {
575                button.prop('disabled', false);
576                if (originalHtml) {
577                    button.html(originalHtml);
578                } else {
579                    textElement.text(casdoorT('sendEmail', 'Send Email'));
580                }
581            }
582        }
583        
584        updateButton();
585    }
586    
587    if (document.getElementById('casdoor-register-step2-form')) {
588        var form = document.getElementById('casdoor-register-step2-form');
589        var passwordInput = document.getElementById('casdoor-password');
590        var passwordHint = document.getElementById('password-hint');
591        
592        function validatePassword() {
593            var password = passwordInput.value;
594            var hasLetter = /[a-zA-Z]/.test(password);
595            var hasNumber = /[0-9]/.test(password);
596            var hasNoSpaces = !/\s/.test(password);
597            var isValidLength = password.length >= 8;
598            
599            return isValidLength && hasLetter && hasNumber && hasNoSpaces;
600        }
601        
602        passwordInput.addEventListener('input', function() {
603            if (passwordHint.classList.contains('error')) {
604                passwordHint.classList.remove('error');
605                passwordHint.textContent = casdoorT('passwordHint', 'At least 8 characters, including letters and numbers, no spaces.');
606            }
607        });
608        
609        form.addEventListener('submit', function(e) {
610            e.preventDefault();
611            
612            if (!validatePassword()) {
613                passwordHint.classList.add('error');
614                passwordHint.textContent = casdoorT('passwordTooWeak', 'Password too weak. Please try a stronger one.');
615                return;
616            }
617            
618            var submitBtn = form.querySelector('.casdoor-auth-login-button');
619            var submitText = submitBtn.querySelector('.casdoor-login-text');
620            var originalText = submitText.textContent;
621            
622            submitBtn.disabled = true;
623            submitText.textContent = casdoorT('processing', 'Processing...');
624            
625            var formData = new FormData(form);
626            formData.append('action', 'casdoor_register_step2');
627            formData.append('nonce', casdoor_ajax.nonce);
628            formData.append('current_url', window.location.href);
629            formData.append('language_code', casdoor_ajax.language_code || '');
630            formData.append('locale', casdoor_ajax.locale || '');
631            
632            jQuery.ajax({
633                url: casdoor_ajax.ajax_url,
634                type: 'POST',
635                data: formData,
636                processData: false,
637                contentType: false,
638                success: function(data) {
639                    if (data.success) {
640                        showMessage('success', casdoorT('passwordSetSuccessfully', 'Password set successfully'));
641                        setTimeout(function() {
642                            window.location.href = data.data.redirect_url;
643                        }, 500);
644                    } else {
645                        showMessage('error', data.data.message || casdoorT('registrationFailedTryAgain', 'Registration failed. Please try again.'));
646                        submitBtn.disabled = false;
647                        submitText.textContent = originalText;
648                    }
649                },
650                error: function() {
651                    showMessage('error', casdoorT('networkErrorOccurredCheckConnection', 'Network error occurred. Please check your connection and try again.'));
652                    submitBtn.disabled = false;
653                    submitText.textContent = originalText;
654                }
655            });
656        });
657    }
658    
659    $('input').on('input', function() {
660        var messagesContainer = $('#casdoor-login-messages');
661        if (messagesContainer.find('.casdoor-message.error').length > 0) {
662            messagesContainer.fadeOut();
663        }
664    });
665    
666});
667
668function casdoorLogout(redirectUrl) {
669    var targetRedirectUrl = redirectUrl || window.location.href || '/';
670    targetRedirectUrl = String(targetRedirectUrl).split('#')[0] || '/';
671    
672    jQuery.ajax({
673        url: casdoor_ajax.ajax_url,
674        type: 'POST',
675        data: {
676            action: 'casdoor_logout',
677            nonce: casdoor_ajax.nonce,
678            redirect_url: targetRedirectUrl
679        },
680        success: function(response) {
681            if (response.success) {
682                // wp_send_json($result) puts fields at top level (not under .data)
683                var targetUrl = response.redirect_url || (response.data && response.data.redirect_url) || targetRedirectUrl || '/';
684                window.location.href = targetUrl;
685            } else {
686                alert(casdoorFormat(casdoorT('logoutFailedPrefix', 'Logout failed: %s'), response.message));
687            }
688        },
689        error: function() {
690            alert(casdoorT('networkErrorTryAgain', 'Network error. Please try again.'));
691        }
692    });
693}
694
695(function bindNpLogoutCapture() {
696    if (window.__casdoorNpLogoutCaptureBound) {
697        return;
698    }
699
700    window.__casdoorNpLogoutCaptureBound = true;
701
702    function getNpLogoutButton(target) {
703        return target && typeof target.closest === 'function' ? target.closest('#np_logout_url') : null;
704    }
705
706    function triggerNpLogout(event) {
707        var button = getNpLogoutButton(event.target);
708
709        if (!button) {
710            return;
711        }
712
713        event.preventDefault();
714        event.stopPropagation();
715        if (typeof event.stopImmediatePropagation === 'function') {
716            event.stopImmediatePropagation();
717        }
718
719        casdoorLogout(window.location.href || '/');
720    }
721
722    document.addEventListener('click', triggerNpLogout, true);
723    document.addEventListener('keydown', function (event) {
724        var button = getNpLogoutButton(event.target);
725
726        if (!button || (event.key !== 'Enter' && event.key !== ' ')) {
727            return;
728        }
729
730        triggerNpLogout(event);
731    }, true);
732})();
733
734function validateAccount(account) {
735    var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
736    var phoneRegex = /^[+]?[\d\s\-()]{10,}$/;
737    
738    return emailRegex.test(account) || phoneRegex.test(account);
739}
740
741function detectAccountType(account) {
742    var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
743    return emailRegex.test(account) ? 'email' : 'phone';
744}
745
746jQuery(document).ready(function($) {
747    $('#casdoor-account').on('blur', function() {
748        var account = $(this).val().trim();
749        $(this).removeClass('casdoor-input-error');
750        $(this).siblings('.casdoor-field-error').remove();
751        
752        if (account && !validateAccount(account)) {
753            $(this).addClass('casdoor-input-error');
754            $(this).after('<div class="casdoor-field-error">' + casdoorT('enterValidEmail', 'Please enter a valid email.') + '</div>');
755        }
756    });
757    
758    $(document).on('click', '.casdoor-logout-link', function(e) {
759        e.preventDefault();
760        var redirectUrl = $(this).data('redirect') || window.location.href || '/';
761        casdoorLogout(redirectUrl);
762    });
763
764    // Support logout button by id (e.g. Elementor button with id="np_logout_url")
765    $(document).on('click', '#np_logout_url', function(e) {
766        e.preventDefault();
767        casdoorLogout(window.location.href || '/');
768    });
769    
770    if (document.getElementById('casdoor-register-step3-form')) {
771        $('#casdoor-country').select2({
772            placeholder: casdoorT('pleaseSelect', 'Please select'),
773            allowClear: false,
774            width: '100%'
775        });
776        
777        $('#casdoor-register-step3-form').on('submit', function(e) {
778            e.preventDefault();
779            
780            var form = $(this);
781            var submitBtn = form.find('.casdoor-auth-login-button');
782            var submitText = submitBtn.find('.casdoor-login-text');
783            var firstName = $('#casdoor-first-name').val().trim();
784            var lastName = $('#casdoor-last-name').val().trim();
785            var country = $('#casdoor-country').val();
786            $('.field-error').hide().text('');
787            
788            var hasError = false;
789            
790            if (!firstName) {
791                $('#casdoor-first-name').siblings('.field-error').text(casdoorT('firstNameRequired', 'First name is required')).show();
792                hasError = true;
793            }
794
795            if (!lastName) {
796                $('#casdoor-last-name').siblings('.field-error').text(casdoorT('lastNameRequired', 'Last name is required')).show();
797                hasError = true;
798            }
799            
800            if (!country) {
801                $('#casdoor-country').siblings('.field-error').text(casdoorT('countryRequired', 'Country is required')).show();
802                hasError = true;
803            }
804            
805            if (hasError) {
806                showMessage('error', casdoorT('fillRequiredFields', 'Please fill in all required fields.'));
807                return;
808            }
809            
810            submitBtn.prop('disabled', true);
811            
812            var formData = new FormData(form[0]);
813            formData.append('action', 'casdoor_register_step3');
814            formData.append('nonce', casdoor_ajax.nonce);
815            formData.append('current_url', window.location.href);
816            formData.append('language_code', casdoor_ajax.language_code || '');
817            formData.append('locale', casdoor_ajax.locale || '');
818            
819            $.ajax({
820                url: casdoor_ajax.ajax_url,
821                type: 'POST',
822                data: formData,
823                processData: false,
824                contentType: false,
825                timeout: 60000, 
826                success: function(response) {
827                    if (response.success) {
828                        if (response.data && response.data.redirect_needed && response.data.redirect_url) {
829                            showMessage('error', casdoorT('redirectingToPasswordSetup', 'Redirecting to password setup...'), true);
830                            setTimeout(function() {
831                                window.location.href = response.data.redirect_url;
832                            }, 1000);
833                            return;
834                        }
835                        
836                        if (response.data && response.data.session_id && response.data.cookie_name) {
837                            var sessionId = response.data.session_id;
838                            var cookieName = response.data.cookie_name;
839                            var duration = response.data.cookie_duration || 86400;
840                            var expiryDate = new Date();
841                            expiryDate.setTime(expiryDate.getTime() + (duration * 1000));
842                            
843                            document.cookie = cookieName + '=' + sessionId + 
844                                '; expires=' + expiryDate.toUTCString() + 
845                                '; path=/' +
846                                '; SameSite=Lax' +
847                                (window.location.protocol === 'https:' ? '; Secure' : '');
848                        }
849                        
850                        // Cross-site sync: if redirect_url is set, follow the chain
851                        if (response.data && response.data.redirect_url) {
852                            window.location.href = response.data.redirect_url;
853                            return;
854                        }
855
856                        var formContainer = form.closest('.casdoor-login-container');
857                        var successHTML = '<div class="casdoor-registration-success">' +
858                            '<div class="casdoor-success-card">' +
859                                '<div class="casdoor-success-heading">' +
860                                    '<h1 class="casdoor-success-title">' + casdoorT('registrationSuccessfulTitle', 'Registration successful') + '</h1>' +
861                                '</div>' +
862                                '<div class="casdoor-success-message-row">' +
863                                    '<div class="casdoor-success-icon">' +
864                                        '<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 64 64" fill="none">' +
865                                            '<circle cx="32" cy="32" r="30" stroke="#22C55E" stroke-width="4" fill="none"/>' +
866                                            '<path d="M20 32L28 40L44 24" stroke="#22C55E" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>' +
867                                        '</svg>' +
868                                    '</div>' +
869                                    '<div class="casdoor-success-copy">' +
870                                        '<h2 class="casdoor-success-subtitle">' + casdoorT('thankYouForRegistering', 'Thank you for registering') + '</h2>' +
871                                        '<p class="casdoor-success-message">' + casdoorT('registrationSuccessMessage', 'You are now a member of the CRYSOUND website, and you can access various services.') + '</p>' +
872                                    '</div>' +
873                                '</div>' +
874                                '<div class="casdoor-success-actions">' +
875                                    '<a href="' + ((casdoor_ajax.urls && casdoor_ajax.urls.account) ? casdoor_ajax.urls.account : (casdo
875or_ajax.home_url + '/account')) + '" class="casdoor-success-button"><span>' + casdoorT('editMyProfile', 'Edit my profile') + '</span></a>' +
876                                '</div>' +
877                            '</div>' +
878                        '</div>';
879                        
880                        formContainer.replaceWith(successHTML);
881                        showMessage('success', casdoorT('registrationCompletedSuccessfully', 'Registration completed successfully!'));
882                    } else {
883                        if (response.data && response.data.show_error_page && response.data.error_url) {
884                            var errorMsg = response.data.message || casdoorT('registrationFailedTryAgain', 'Registration failed. Please try again.');
885                            showMessage('error', casdoorFormat(casdoorT('registrationFailedPrefix', 'Registration failed: %s. Redirecting to error page...'), errorMsg));
886                            
887                            setTimeout(function() {
888                                window.location.href = response.data.error_url;
889                            }, 2000);
890                        } else {
891                            var errorMsg = response.data && response.data.message ? response.data.message : casdoorT('registrationFailedTryAgain', 'Registration failed. Please try again.');
892                            var debugInfo = response.data && response.data.debug_info ? ' (Details: ' + response.data.debug_info + ')' : '';
893                            var enhancedMsg = errorMsg;
894                            if (errorMsg.includes('Unauthorized operation')) {
895                                enhancedMsg = casdoorT('registrationServiceUnavailable', 'Registration service is temporarily unavailable. Please try again later.');
896                            } else if (errorMsg.includes('user already exists')) {
897                                enhancedMsg = casdoorT('accountAlreadyExists', 'An account with this email already exists. Please try logging in instead.');
898                            }
899                            
900                            showMessage('error', enhancedMsg + debugInfo);
901                            submitBtn.prop('disabled', false);
902                            submitText.text(casdoorT('processingComplete', 'Complete'));
903                        }
904                    }
905                },
906                error: function(xhr, status, error) {
907                    var errorMessage = casdoorT('networkErrorTryAgain', 'Network error. Please try again.');
908                    
909                    try {
910                        if (xhr.responseText) {
911                            var errorResponse = JSON.parse(xhr.responseText);
912                            if (errorResponse.data && errorResponse.data.message) {
913                                errorMessage = errorResponse.data.message;
914                            }
915                        }
916                    } catch (e) {
917                    }
918                    
919                    if (status === 'timeout') {
920                        errorMessage = casdoorT('requestTimeoutAccountCreated', 'Request timeout. Your account may have been created. Please try logging in, or refresh this page to check.');
921                    } else if (xhr.status === 0) {
922                        errorMessage = casdoorT('connectionFailedRetry', 'Connection failed. Please check your network and try again.');
923                    }
924                    
925                    showMessage('error', errorMessage);
926                    submitBtn.prop('disabled', false);
927                    submitText.text(casdoorT('processingComplete', 'Complete'));
928                }
929            });
930        });
931    }
932});
933
934function togglePasswordVisibility(inputId, iconElement) {
935    var passwordInput = document.getElementById(inputId);
936    var isPassword = passwordInput.type === 'password';
937    
938    passwordInput.type = isPassword ? 'text' : 'password';
939    
940    var eyeIcon = iconElement.querySelector('svg');
941    if (isPassword) {
942        // set to visible-eye (open)
943        eyeIcon.innerHTML = '<g clip-path="url(#clip0_512_11558)"><path d="M0.666992 7.99984C0.666992 7.99984 3.33366 2.6665 8.00033 2.6665C12.667 2.6665 15.3337 7.99984 15.3337 7.99984C15.3337 7.99984 12.667 13.3332 8.00033 13.3332C3.33366 13.3332 0.666992 7.99984 0.666992 7.99984Z" stroke="#888888" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
943<path d="M8.00033 9.99984C9.1049 9.99984 10.0003 9.10441 10.0003 7.99984C10.0003 6.89527 9.1049 5.99984 8.00033 5.99984C6.89576 5.99984 6.00033 6.89527 6.00033 7.99984C6.00033 9.10441 6.89576 9.99984 8.00033 9.99984Z" stroke="#888888" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></g><defs><clipPath id="clip0_512_11558"><rect width="16" height="16" fill="white"/></clipPath></defs>';
944    } else {
945        // set to hidden-eye (with slash)
946        eyeIcon.innerHTML = '<g clip-path="url(#clip0_512_11563)"><path d="M6.60033 2.8265C7.05921 2.71909 7.52904 2.6654 8.00033 2.6665C12.667 2.6665 15.3337 7.99984 15.3337 7.99984C14.929 8.75691 14.4464 9.46966 13.8937 10.1265M9.41366 9.41317C9.23056 9.60967 9.00976 9.76727 8.76443 9.87659C8.5191 9.9859 8.25426 10.0447 7.98572 10.0494C7.71718 10.0542 7.45043 10.0048 7.2014 9.90416C6.95236 9.80358 6.72614 9.65386 6.53622 9.46394C6.34631 9.27402 6.19659 9.0478 6.096 8.79876C5.99541 8.54973 5.94601 8.28298 5.95075 8.01444C5.95549 7.7459 6.01426 7.48107 6.12358 7.23574C6.23289 6.9904 6.39049 6.7696 6.58699 6.5865M0.666992 0.666504L15.3337 15.3332M11.9603 11.9598C10.8207 12.8285 9.43306 13.3097 8.00033 13.3332C3.33366 13.3332 0.666992 7.99984 0.666992 7.99984C1.49625 6.45443 2.64642 5.10424 4.04033 4.03984L11.9603 11.9598Z" stroke="#888888" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></g><defs><clipPath id="clip0_512_11563"><rect width="16" height="16" fill="white"/></clipPath></defs>';
947    }
948}
949
950(function($) {
951    'use strict';
952    
953    function initTabs() {
954        var tabs = $('.upc-content .upc-tab');
955        var tabContents = $('.upc-content .upc-tab-content');
956        
957        if (tabs.length === 0 || tabContents.length === 0) return;
958        
959        tabContents.not('.active').hide();
960        
961        var savedMenu = '';
962        var savedTab = '';
963
964        try {
965            savedMenu = sessionStorage.getItem('upc_active_menu') || '';
966            savedTab = sessionStorage.getItem('upc_active_tab') || '';
967        } catch (err) {}
968
969        if ((savedMenu === 'my-orders' || savedMenu === 'address-book') && savedTab) {
970            try {
971                sessionStorage.removeItem('upc_active_tab');
972            } catch (err) {}
973            savedTab = '';
974        }
975
976        if (savedTab && $('.upc-content .upc-tab[data-content="' + savedTab + '"]').length) {
977            tabs.removeClass('active');
978            $('.upc-content .upc-tab[data-content="' + savedTab + '"]').addClass('active');
979            tabContents.removeClass('active').hide();
980            $('.upc-content #' + savedTab).addClass('active').show();
981        }
982        
983        tabs.off('click.upctab').on('click.upctab', function(e) {
984            e.preventDefault();
985            e.stopPropagation();
986            
987            var $this = $(this);
988            var contentId = $this.attr('data-content');
989            
990            if (!contentId) return;
991            
992            var $content = $this.closest('.upc-content');
993            $content.find('.upc-tab').removeClass('active');
994            $content.find('.upc-tab-content').removeClass('active').hide();
995            
996            $this.addClass('active');
997            $content.find('#' + contentId).addClass('active').show();
998            
999            sessionStorage.setItem('upc_active_tab', contentId);
1000            sessionStorage.setItem('upc_active_menu', 'profile-settings');
1001        });
1002    }
1003    
1004    // Handle Return button click
1005    $(document).on('click', '#upc-return', function() {
1006        if ($(window).width() <= 1024) {
1007            if ($('.upc-container').hasClass('show-content')) {
1008                $('.upc-container').removeClass('show-content settings-active');
1009                $('.upc-return').removeClass('show-content');
1010            } else {
1011                window.history.back();
1012            }
1013        } else {
1014            window.history.back();
1015        }
1016    });
1017    
1018    function initMenuItems() {
1019        var menuItems = $('.upc-menu-item');
1020        var tabs = $('.upc-tab');
1021        
1022        menuItems.off('click.upcmenu').on('click.upcmenu', function(e) {
1023            e.preventDefault();
1024            e.stopPropagation();
1025            
1026            var $this = $(this);
1027            var tabName = $this.attr('data-tab');
1028            
1029            if (!tabName) return;
1030            
1031            menuItems.removeClass('active');
1032            $this.addClass('active');
1033            
1034            var correspondingTab = tabs.filter('[data-content="' + tabName + '"]');
1035            if (correspondingTab.length) {
1036                tabs.removeClass('active');
1037                correspondingTab.addClass('active');
1038                
1039                $('.upc-tab-content').removeClass('active').hide();
1040                $('#' + tabName).addClass('active').show();
1041                
1042                sessionStorage.setItem('upc_active_tab', tabName);
1043                sessionStorage.setItem('upc_active_menu', 'profile-settings');
1044            }
1045            
1046            if ($(window).width() <= 1024) {
1047                $('.upc-container').addClass('show-content');
1048                $('.upc-return').addClass('show-content');
1049
1050                // Only mark container as settings-active when opening Settings
1051                if ($this.data('tab') === 'profile-settings' || $this.attr('href') === '#profile-settings') {
1052                    $('.upc-container').addClass('settings-active');
1053                } else {
1054                    $('.upc-container').removeClass('settings-active');
1055                }
1056            }
1057            
1058            var menuText = $this.find('span').text();
1059            $('.upc-breadcrumb-current').text(menuText);
1060        });
1061    }
1062    
1063    if (document.readyState === 'loading') {
1064        $(document).ready(function() {
1065            initTabs();
1066            initMenuItems();
1067        });
1068    } else {
1069        initTabs();
1070        initMenuItems();
1071    }
1072    
1073    $(window).on('load', function() {
1074        if ($('.upc-tab').length > 0 && $('.upc-tab').data('events') === undefined) {
1075            initTabs();
1076            initMenuItems();
1077        }
1078    });
1079    
1080})(jQuery);
1081
1082jQuery(document).ready(function($) {
1083    'use strict';
1084    
1085    $('#upload-avatar-btn').on('click', function() {
1086        $('#avatar-input').click();
1087    });
1088    
1089    $('#avatar-input').on('change', function() {
1090        var file = this.files[0];
1091        if (file) {
1092            var reader = new FileReader();
1093            reader.onload = function(e) {
1094                $('#preview-avatar').attr('src', e.target.result);
1095            };
1096            reader.readAsDataURL(file);
1097            
1098            var formData = new FormData();
1099            formData.append('action', 'upc_upload_avatar');
1100            formData.append('nonce', upc_ajax.nonce);
1101            formData.append('avatar', file);
1102            
1103            $.ajax({
1104                url: upc_ajax.ajax_url,
1105                type: 'POST',
1106                data: formData,
1107                processData: false,
1108                contentType: false,
1109                success: function(response) {
1110                    if (response.success) {
1111                        showMessage('success', casdoorT('avatarUploadedSuccessfully', 'Avatar uploaded successfully!'));
1112                        $('.upc-avatar-small, .upc-avatar-large').attr('src', response.data.avatar_url);
1113                    } else {
1114                        showMessage('error', (response.data && response.data.message) ? response.data.message : casdoorT('uploadFailed', 'Upload failed'));
1115                    }
1116                },
1117                error: function() {
1118                    showMessage('error', casdoorT('uploadFailedTryAgain', 'Upload failed. Please try again.'));
1119                }
1120            });
1121        }
1122    });
1123    
1124    $('#basic-info-form').on('submit', function(e) {
1125        e.preventDefault();
1126        
1127        // 防止重复提交
1128        var $form = $(this);
1129        var $submitBtn = $form.find('button[type="submit"]');
1130        if ($submitBtn.prop('disabled')) {
1131            return false;
1132        }
1133        
1134        var phone = $('input[name="phone"]').val().trim();
1135        
1136        if (phone && (phone.length < 7 || phone.length > 20)) {
1137            showMessage('error', casdoorT('phoneLengthError', 'Phone number should be 7-20 characters.'));
1138            return;
1139        }
1140        
1141        var phoneRegex = /^[0-9+\-\s()]*$/;
1142        if (phone && !phoneRegex.test(phone)) {
1143            showMessage('error', casdoorT('phoneCharactersError', 'Phone number should only contain numbers, +, -, spaces, and ().'));
1144            return;
1145        }
1146        
1147        if (typeof upc_ajax === 'undefined' || !upc_ajax.nonce) {
1148            showMessage('error', casdoorT('securityTokenNotFound', 'Security token not found. Please refresh the page.'));
1149            return;
1150        }
1151        
1152        // 禁用按钮并显示加载状态
1153        $submitBtn.prop('disabled', true);
1154        var originalText = $submitBtn.text();
1155        $submitBtn.text(casdoorT('saving', 'Saving...'));
1156        
1157        var formData = $(this).serialize();
1158        formData += '&action=upc_update_basic_info&nonce=' + upc_ajax.nonce;
1159        
1160        console.log('Submitting basic info update:', {
1161            url: upc_ajax.ajax_url,
1162            data: formData
1163        });
1164        
1165        $.ajax({
1166            url: upc_ajax.ajax_url,
1167            type: 'POST',
1168            data: formData,
1169            success: function(response) {
1170                console.log('Server response:', response); // 🔍 调试日志
1171                
1172                // 恢复按钮状态
1173                $submitBtn.prop('disabled', false).text(originalText);
1174                
1175                if (response.success) {
1176                    showMessage('success', casdoorT('basicInfoUpdated', 'Basic info updated successfully!'));
1177                    if (response.data && response.data.email) {
1178                        $('.upc-email').text(response.data.email);
1179                    }
1180                } else {
1181                    var errorMessage = casdoorT('updateFailed', 'Update failed');
1182                    if (response.data && response.data.message) {
1183                        errorMessage = response.data.message;
1184                    }
1185                    console.error('Update failed:', errorMessage, 'Full response:', response); // 🔍 调试日志
1186                    showMessage('error', errorMessage);
1187                }
1188            },
1189            error: function(xhr, status, error) {
1190                // 恢复按钮状态
1191                $submitBtn.prop('disabled', false).text(originalText);
1192                
1193                var errorMessage = casdoorT('updateFailedTryAgain', 'Update failed. Please try again.');
1194                if (xhr.status === 403) {
1195                    errorMessage = casdoorT('securityCheckFailed', 'Security check failed. Please refresh the page and try again.');
1196                } else if (xhr.status === 500) {
1197                    errorMessage = casdoorT('serverErrorContactAdmin', 'Server error. Please contact administrator.');
1198                } else if (xhr.responseText) {
1199                    try {
1200                        var response = JSON.parse(xhr.responseText);
1201                        if (response.data && response.data.message) {
1202                            errorMessage = response.data.message;
1203                        }
1204                    } catch(e) {
1205                        // JSON parse failed, use default message
1206                    }
1207                }
1208                showMessage('error', errorMessage);
1209            }
1210        });
1211    });
1212    
1213    $('#company-info-form').on('submit', function(e) {
1214        e.preventDefault();
1215        
1216        // 防止重复提交
1217        var $form = $(this);
1218        var $submitBtn = $form.find('button[type="submit"]');
1219        if ($submitBtn.prop('disabled')) {
1220            return false;
1221        }
1222        
1223        if (typeof upc_ajax === 'undefined' || !upc_ajax.nonce) {
1224            showMessage('error', casdoorT('securityTokenNotFound', 'Security token not found. Please refresh the page.'));
1225            return;
1226        }
1227        
1228        // 禁用按钮并显示加载状态
1229        $submitBtn.prop('disabled', true);
1230        var originalText = $submitBtn.text();
1231        $submitBtn.text(casdoorT('saving', 'Saving...'));
1232        
1233        var formData = $(this).serialize();
1234        formData += '&action=upc_update_company_info&nonce=' + upc_ajax.nonce;
1235        
1236        $.ajax({
1237            url: upc_ajax.ajax_url,
1238            type: 'POST',
1239            data: formData,
1240            success: function(response) {
1241                // 恢复按钮状态
1242                $submitBtn.prop('disabled', false).text(originalText);
1243                
1244                if (response.success) {
1245                    showMessage('success', casdoorT('companyInfoUpdated', 'Company info updated successfully!'));
1246                } else {
1247                    var errorMessage = casdoorT('updateFailed', 'Update failed');
1248                    if (response.data && response.data.message) {
1249                        errorMessage = response.data.message;
1250                    }
1251                    showMessage('error', errorMessage);
1252                }
1253            },
1254            error: function(xhr, status, error) {
1255                // 恢复按钮状态
1256                $submitBtn.prop('disabled', false).text(originalText);
1257                
1258                var errorMessage = casdoorT('updateFailedTryAgain', 'Update failed. Please try again.');
1259                if (xhr.status === 403) {
1260                    errorMessage = casdoorT('securityCheckFailed', 'Security check failed. Please refresh the page and try again.');
1261                } else if (xhr.status === 500) {
1262                    errorMessage = casdoorT('serverErrorContactAdmin', 'Server error. Please contact administrator.');
1263                } else if (xhr.responseText) {
1264                    try {
1265                        var response = JSON.parse(xhr.responseText);
1266                        if (response.data && response.data.message) {
1267                            errorMessage = response.data.message;
1268                        }
1269                    } catch(e) {
1270                        // JSON parse failed, use default message
1271                    }
1272                }
1273                showMessage('error', errorMessage);
1274            }
1275        });
1276    });
1277    
1278    $('#change-password-form').on('submit', function(e) {
1279        e.preventDefault();
1280        
1281        var newPassword = $('input[name="new_password"]').val();
1282        
1283        if (!newPassword) {
1284            showMessage('error', casdoorT('enterPassword', 'Please enter your password.'));
1285            return;
1286        }
1287        
1288        if (!validatePassword(newPassword)) {
1289            showMessage('error', casdoorT('passwordRequirementsNotMet', 'Password does not meet requirements'));
1290            return;
1291        }
1292        
1293        if (typeof upc_ajax === 'undefined' || !upc_ajax.nonce) {
1294            showMessage('error', casdoorT('securityTokenNotFound', 'Security token not found. Please refresh the page.'));
1295            return;
1296        }
1297        
1298        var formData = $(this).serialize();
1299        formData += '&action=upc_change_password&nonce=' + upc_ajax.nonce;
1300        
1301        $.ajax({
1302            url: upc_ajax.ajax_url,
1303            type: 'POST',
1304            data: formData,
1305            success: function(response) {
1306                if (response.success) {
1307                    showMessage('success', response.data.message || casdoorT('passwordChangedSuccessfully', 'Password changed successfully!'));
1308                    $('#change-password-form')[0].reset();
1309                    
1310                    window.location.replace(response.data.redirect_url || ((casdoor_ajax.urls && casdoor_ajax.urls.login) ? casdoor_ajax.urls.login : '/login'));
1311                } else {
1312                    showMessage('error', (response.data && response.data.message) ? response.data.message : casdoorT('updateFailed', 'Update failed'));
1313                }
1314            },
1315            error: function(xhr, status, error) {
1316                var errorMessage = casdoorT('updateFailedTryAgain', 'Update failed. Please try again.');
1317                if (xhr.status === 403) {
1318                    errorMessage = casdoorT('securityCheckFailed', 'Security check failed. Please refresh the page and try again.');
1319                } else if (xhr.status === 500) {
1320                    errorMessage = casdoorT('serverErrorContactAdmin', 'Server error. Please contact administrator.');
1321                } else if (xhr.responseText) {
1322                    try {
1323                        var response = JSON.parse(xhr.responseText);
1324                        if (response.data && response.data.message) {
1325                            errorMessage = response.data.message;
1326                        }
1327                    } catch(e) {
1328                        // JSON parse failed, use default message
1329                    }
1330                }
1331                showMessage('error', errorMessage);
1332            }
1333        });
1334    });
1335    
1336    function validatePassword(password) {
1337        if (password.length < 8) return false;
1338        if (!/[a-z]/.test(password)) return false;
1339        if (!/[A-Z]/.test(password)) return false;
1340        if (!/[0-9]/.test(password)) return false;
1341        if (!/[^a-zA-Z0-9]/.test(password)) return false;
1342        return true;
1343    }
1344    
1345    $('.upc-toggle-password').on('click', function() {
1346        var input = $(this).siblings('input');
1347        var type = input.attr('type');
1348        var eyeOpen = $(this).find('.eye-open');
1349        var eyeClosed = $(this).find('.eye-closed');
1350        
1351        if (type === 'password') {
1352            input.attr('type', 'text');
1353            eyeOpen.show();
1354            eyeClosed.hide();
1355        } else {
1356            input.attr('type', 'password');
1357            eyeOpen.hide();
1358            eyeClosed.show();
1359        }
1360    });
1361    
1362    $('.upc-btn-cancel').on('click', function() {
1363        var form = $(this).closest('form');
1364        form[0].reset();
1365    });
1366    
1367    // 登录成功后默认跳转到账户页。
1368    // 仅对显式声明要保留返回页的链接附加 redirect_to,避免跳回缓存的游客页。
1369    function addRedirectToLoginLinks() {
1370        var currentUrl = window.location.href;
1371        var loginPageUrl = (casdoor_ajax.urls && casdoor_ajax.urls.login) ? casdoor_ajax.urls.login : (casdoor_ajax.home_url + '/login');
1372        var registerPageUrl = (casdoor_ajax.urls && casdoor_ajax.urls.register) ? casdoor_ajax.urls.register : (casdoor_ajax.home_url + '/register');
1373        var forgotPasswordUrl = (casdoor_ajax.urls && casdoor_ajax.urls.forgot_password) ? casdoor_ajax.urls.forgot_password : (casdoor_ajax.home_url + '/forgot-password');
1374        var accountPageUrl = (casdoor_ajax.urls && casdoor_ajax.urls.account) ? casdoor_ajax.urls.account : (casdoor_ajax.home_url + '/account');
1375        // 如果当前页面是登录、注册、忘记密码或账户页面,不添加 redirect_to
1376        if (currentUrl.indexOf(loginPageUrl) !== -1 || 
1377            currentUrl.indexOf(registerPageUrl) !== -1 || 
1378            currentUrl.indexOf(forgotPasswordUrl) !== -1 ||
1379            currentUrl.indexOf(accountPageUrl) !== -1 ||
1380            currentUrl.indexOf('/login') !== -1 || 
1381            currentUrl.indexOf('/register') !== -1 || 
1382            currentUrl.indexOf('/forgot-password') !== -1 ||
1383            currentUrl.indexOf('/account') !== -1 ||
1384            currentUrl.indexOf('/user-center') !== -1) {
1385            return;
1386        }
1387        
1388        // 查找所有指向登录页面的链接
1389        $('a').each(function() {
1390            var $link = $(this);
1391            var href = $link.attr('href');
1392            var preserveRedirect = $link.is('[data-casdoor-preserve-redirect="true"]');
1393            
1394            // 如果链接已经有 redirect_to 参数,跳过
1395            if (preserveRedirect && href && href.indexOf('redirect_to=') === -1) {
1396                // 确保链接指向登录页面
1397                if (href.indexOf(loginPageUrl) !== -1 || href.indexOf('/login') !== -1) {
1398                    var separator = href.indexOf('?') === -1 ? '?' : '&';
1399                    var newHref = href + separator + 'redirect_to=' + encodeURIComponent(currentUrl);
1400                    $link.attr('href', newHref);
1401                }
1402            }
1403        });
1404    }
1405    
1406    // 页面加载时执行
1407    addRedirectToLoginLinks();
1408    
1409    // 监听DOM变化,处理动态加载的登录链接(如移动菜单)
1410    var observer = new MutationObserver(function(mutations) {
1411        addRedirectToLoginLinks();
1412    });
1413    
1414    // 观察body的子节点变化
1415    observer.observe(document.body, {
1416        childList: true,
1417        subtree: true
1418    });
1419});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.