Files
wordpress-theme-aksrt/assets/js/routes/user-center.js
T
kate522 815e83bac0 fix(user-center): complete certification and order flows
Fix modal scroll ownership and certification modal styling, store evidence as Media Library attachments, reconcile missed provider callbacks, validate currencies, and complete digital fulfillment only after durable entitlement delivery.
2026-07-29 10:29:59 +08:00

876 lines
31 KiB
JavaScript

/**
* AKSRT User Center — 本人中心专属脚本
*
* 从 page-profile.php 内联 JS 迁移而来。
* 依赖全局 aksrtUserCenter 配置对象(由模板注入)。
*
* @package AKSRT
*/
/* global aksrtUserCenter, showToast */
(function() {
'use strict';
var cfg = window.aksrtUserCenter || {};
var ajaxUrl = cfg.ajaxUrl || '';
var publicNonce = cfg.publicNonce || '';
var settingsNonce = cfg.settingsNonce || '';
var userId = cfg.userId || 0;
var i18n = cfg.i18n || {};
var tabAliases = cfg.tabAliases || {};
var tabUrls = cfg.tabUrls || {};
/* ==================== Dashboard 导航 ==================== */
function initDashboardNavigation() {
var tabContainer = document.querySelector('.uc-mobile-tabs');
if (!tabContainer) return;
var tabs = tabContainer.querySelectorAll('[data-tab]');
var sidebarBtns = document.querySelectorAll('.uc-sidebar__btn[data-tab], .uc-service-grid__item[data-tab]');
var panels = {};
var defaultTab = cfg.defaultTab || 'profile';
var drawerTrigger = document.getElementById('uc-drawer-trigger');
var drawerOverlay = document.getElementById('uc-drawer-overlay');
var sidebar = document.querySelector('.uc-sidebar');
tabs.forEach(function(tab) {
var name = tab.getAttribute('data-tab');
var panel = document.getElementById('panel-' + name);
if (panel) {
panels[name] = { tab: tab, panel: panel };
}
});
function openDrawer() {
if (sidebar) sidebar.classList.add('is-open');
if (drawerOverlay) drawerOverlay.classList.add('is-visible');
document.body.style.overflow = 'hidden';
}
function closeDrawer() {
if (sidebar) sidebar.classList.remove('is-open');
if (drawerOverlay) drawerOverlay.classList.remove('is-visible');
document.body.style.overflow = '';
}
function switchTo(name) {
if (!panels[name]) name = defaultTab;
if (panels[name].panel.dataset.panelLoaded === 'false') {
window.location.assign(tabUrls[name] || panels[name].panel.dataset.tabUrl || ('?tab=' + encodeURIComponent(name)));
return;
}
Object.keys(panels).forEach(function(key) {
var active = key === name;
panels[key].tab.classList.toggle('is-active', active);
panels[key].tab.setAttribute('aria-selected', active ? 'true' : 'false');
panels[key].panel.classList.toggle('is-active', active);
panels[key].panel.hidden = !active;
});
sidebarBtns.forEach(function(btn) {
btn.classList.toggle('is-active', btn.getAttribute('data-tab') === name);
});
closeDrawer();
}
function tabFromUrl() {
var m = window.location.search.match(/[?&]tab=([^&]+)/);
var name = m ? decodeURIComponent(m[1]) : (cfg.activeTab || defaultTab);
return tabAliases[name] || name;
}
function updateUrl(name) {
if (!window.history.replaceState) return;
var u = new URL(window.location);
if (name === defaultTab) {
u.searchParams.delete('tab');
} else {
u.searchParams.set('tab', name);
}
window.history.replaceState({}, '', u);
}
tabs.forEach(function(tab) {
tab.addEventListener('click', function(e) {
var name = this.getAttribute('data-tab');
if (!panels[name] || panels[name].panel.dataset.panelLoaded === 'false') return;
e.preventDefault();
switchTo(name);
updateUrl(name);
});
});
sidebarBtns.forEach(function(btn) {
btn.addEventListener('click', function(e) {
var name = this.getAttribute('data-tab');
if (!panels[name] || panels[name].panel.dataset.panelLoaded === 'false') return;
e.preventDefault();
switchTo(name);
updateUrl(name);
});
});
if (drawerTrigger) drawerTrigger.addEventListener('click', openDrawer);
if (drawerOverlay) drawerOverlay.addEventListener('click', closeDrawer);
switchTo(tabFromUrl());
}
/* ==================== 个人信息保存 ==================== */
function initProfileForm() {
var form = document.getElementById('profile-form');
if (!form) return;
var iconOptions = '<option value="">—</option>'
+ '<option value="github">GitHub</option>'
+ '<option value="google">Google</option>'
+ '<option value="x">X</option>'
+ '<option value="email">邮箱</option>'
+ '<option value="wechat">微信</option>'
+ '<option value="qq">QQ</option>'
+ '<option value="weibo">微博</option>'
+ '<option value="telegram">Telegram</option>'
+ '<option value="discord">Discord</option>'
+ '<option value="bilibili">Bilibili</option>'
+ '<option value="linkedin">LinkedIn</option>'
+ '<option value="facebook">Facebook</option>'
+ '<option value="youtube">YouTube</option>'
+ '<option value="instagram">Instagram</option>'
+ '<option value="web">网站</option>';
var addBtn = document.getElementById('add-contact-btn');
if (addBtn) {
addBtn.addEventListener('click', function() {
var list = document.getElementById('contacts-list');
var idx = list.children.length;
var div = document.createElement('div');
div.className = 'contact-row';
div.dataset.index = idx;
div.innerHTML =
'<select name="contacts[' + idx + '][icon]" class="profile-input contact-icon">' + iconOptions + '</select>' +
'<input type="hidden" name="contacts[' + idx + '][name]" value="">' +
'<input type="url" name="contacts[' + idx + '][url]" class="profile-input contact-url" placeholder="' + (i18n.contactUrlPlaceholder || '链接 URL') + '">' +
'<button type="button" class="contact-remove" onclick="this.parentElement.remove()" title="' + (i18n.deleteLabel || '删除') + '">&times;</button>';
list.appendChild(div);
});
}
form.addEventListener('submit', function(e) {
e.preventDefault();
var btn = document.getElementById('profile-save-btn');
var msg = document.getElementById('profile-save-msg');
btn.disabled = true;
btn.textContent = i18n.saving || '保存中…';
msg.className = 'profile-form__submit-msg';
msg.textContent = '';
var data = new FormData(form);
data.append('user_id', String(userId));
fetch(ajaxUrl, { method: 'POST', body: data })
.then(function(r) { return r.json(); })
.then(function(res) {
btn.disabled = false;
btn.textContent = i18n.saveBtn || '保存修改';
if (res.success) {
showToast(i18n.saved || '已保存');
} else {
msg.className = 'profile-form__submit-msg is-error';
msg.textContent = res.data.message || (i18n.saveFailed || '保存失败');
}
})
.catch(function() {
btn.disabled = false;
btn.textContent = i18n.saveBtn || '保存修改';
msg.className = 'profile-form__submit-msg is-error';
msg.textContent = i18n.networkError || '网络错误,请重试';
});
});
}
function initAuthForm() {
var modal = document.getElementById('uc-auth-modal');
if (!modal || modal.dataset.authModalBound === '1') return;
modal.dataset.authModalBound = '1';
function openModal() {
modal.classList.add('is-open');
modal.setAttribute('aria-hidden', 'false');
document.body.style.overflow = 'hidden';
var first = modal.querySelector('input:not([type="hidden"]), select, textarea, button');
if (first) window.setTimeout(function() { first.focus(); }, 80);
}
function closeModal() {
modal.classList.remove('is-open');
modal.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
}
document.querySelectorAll('[data-auth-modal-open]').forEach(function(button) {
button.addEventListener('click', openModal);
});
modal.querySelectorAll('[data-auth-modal-close]').forEach(function(button) {
button.addEventListener('click', closeModal);
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.classList.contains('is-open')) closeModal();
});
var fileInput = modal.querySelector('[data-auth-files]');
var previews = modal.querySelector('[data-auth-previews]');
if (fileInput && previews) {
fileInput.addEventListener('change', function() {
previews.innerHTML = '';
var files = Array.prototype.slice.call(fileInput.files || []);
if (files.length > 3) {
showToast('证明材料最多上传 3 张');
fileInput.value = '';
return;
}
for (var index = 0; index < files.length; index++) {
if (files[index].size > 2 * 1024 * 1024) {
showToast('单张图片不能超过 2MB');
fileInput.value = '';
previews.innerHTML = '';
return;
}
var image = document.createElement('img');
image.src = URL.createObjectURL(files[index]);
image.alt = '';
image.onload = function() { URL.revokeObjectURL(this.src); };
previews.appendChild(image);
}
});
}
var form = modal.querySelector('.aksrt-user-auth-form');
if (!form) return;
form.addEventListener('submit', function(e) {
e.preventDefault();
var button = form.querySelector('[type="submit"]');
var message = form.querySelector('[data-auth-message]');
var original = button ? button.textContent : '';
if (button) {
button.disabled = true;
button.textContent = i18n.submitting || '提交中…';
}
if (message) message.textContent = '';
fetch(ajaxUrl, { method: 'POST', body: new FormData(form), credentials: 'same-origin' })
.then(function(response) {
return response.json().then(function(payload) {
if (!response.ok || !payload || !payload.success) {
throw new Error((payload && payload.data && payload.data.message) || '提交失败');
}
return payload.data || {};
});
})
.then(function(data) {
showToast(data.message || '提交成功');
window.setTimeout(function() { window.location.assign(tabUrls.auth || '?tab=auth'); }, 500);
})
.catch(function(error) {
if (message) message.textContent = error.message || '提交失败';
showToast(error.message || '提交失败');
if (button) {
button.disabled = false;
button.textContent = original;
}
});
});
}
/* ==================== 列表内取消收藏 ==================== */
function initUnfavorite() {
var list = document.querySelector('.profile-list[data-list="favorites"]');
if (!list) return;
list.addEventListener('click', function(e) {
var btn = e.target.closest('[data-action="unfavorite"]');
if (!btn) return;
e.preventDefault();
var postId = btn.getAttribute('data-post-id');
if (!postId || btn.disabled) return;
if (!confirm(i18n.confirmUnfavorite || '确定取消收藏这篇文章?')) return;
btn.disabled = true;
btn.classList.add('is-loading');
var body = new URLSearchParams();
body.set('action', 'aksrt_toggle_favorite');
body.set('postId', postId);
body.set('nonce', publicNonce);
body.set('active', '0');
fetch(ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
credentials: 'same-origin',
body: body.toString()
})
.then(function(r) { return r.json(); })
.then(function(res) {
if (res && res.success) {
var item = btn.closest('.profile-list-item');
if (item) {
item.classList.add('is-removing');
setTimeout(function() {
if (item.parentNode) item.parentNode.removeChild(item);
if (!list.querySelector('.profile-list-item')) {
// Show empty state instead of reloading
var empty = document.createElement('div');
empty.className = 'profile-empty';
empty.innerHTML = '<div class="profile-empty__icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" width="30" height="30"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></div><p class="profile-empty__title">暂无收藏</p><p class="profile-empty__desc">你还没有收藏任何文章。</p>';
list.parentNode.replaceChild(empty, list);
}
}, 220);
}
showToast(i18n.unfavorited || '已取消收藏');
} else {
btn.disabled = false;
btn.classList.remove('is-loading');
showToast((res && res.data && res.data.message) || (i18n.operationFailed || '操作失败'));
}
})
.catch(function() {
btn.disabled = false;
btn.classList.remove('is-loading');
showToast(i18n.networkError || '网络错误');
});
});
}
/* ==================== 通知中心 ==================== */
function initNotifications() {
var list = document.getElementById('aksrt-notification-list');
var markAllBtn = document.getElementById('aksrt-mark-all-notifications-read');
var markSelectedBtn = document.getElementById('aksrt-mark-selected-notifications-read');
var deleteSelectedBtn = document.getElementById('aksrt-delete-selected-notifications');
if (!list) return;
function markRead(notificationId, markAll) {
var body = new URLSearchParams();
body.set('action', 'aksrt_mark_notification_read');
body.set('nonce', publicNonce);
if (markAll) {
body.set('mark_all', '1');
} else {
body.set('notification_id', notificationId);
}
return fetch(ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
credentials: 'same-origin',
body: body.toString()
}).then(function(r) { return r.json(); });
}
// 单条标记已读 / 删除
list.addEventListener('click', function(e) {
var btn = e.target.closest('.aksrt-notification-read-btn');
if (btn) {
var id = btn.getAttribute('data-notification-id');
if (!id || btn.disabled) return;
btn.disabled = true;
markRead(id, false).then(function(res) {
if (res && res.success) {
var row = btn.closest('[data-notification-id]');
if (row) row.classList.add('is-read');
btn.remove();
showToast(i18n.markedRead || '已标记为已读');
} else {
btn.disabled = false;
showToast((res && res.data && res.data.message) || (i18n.operationFailed || '操作失败'));
}
}).catch(function() {
btn.disabled = false;
showToast(i18n.networkError || '网络错误');
});
return;
}
var delBtn = e.target.closest('.aksrt-notification-delete-btn');
if (!delBtn) return;
var delId = delBtn.getAttribute('data-notification-id');
if (!delId || delBtn.disabled) return;
if (!confirm(i18n.confirmDeleteNotification || '确定删除这条通知?')) return;
delBtn.disabled = true;
var body = new URLSearchParams();
body.set('action', 'aksrt_delete_notification');
body.set('nonce', publicNonce);
body.set('notification_id', delId);
fetch(ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
credentials: 'same-origin',
body: body.toString()
}).then(function(r) { return r.json(); }).then(function(res) {
if (res && res.success) {
var delRow = delBtn.closest('[data-notification-id]');
if (delRow) delRow.remove();
showToast(i18n.notificationDeleted || '已删除通知');
} else {
delBtn.disabled = false;
showToast((res && res.data && res.data.message) || (i18n.operationFailed || '操作失败'));
}
}).catch(function() {
delBtn.disabled = false;
showToast(i18n.networkError || '网络错误');
});
});
// 全部已读
if (markAllBtn) {
markAllBtn.addEventListener('click', function() {
if (markAllBtn.disabled) return;
markAllBtn.disabled = true;
markRead('', true).then(function(res) {
if (res && res.success) {
list.querySelectorAll('[data-notification-id]').forEach(function(row) {
row.classList.add('is-read');
});
list.querySelectorAll('.aksrt-notification-read-btn').forEach(function(b) { b.remove(); });
showToast(i18n.allMarkedRead || '已全部标记为已读');
} else {
markAllBtn.disabled = false;
showToast((res && res.data && res.data.message) || (i18n.operationFailed || '操作失败'));
}
}).catch(function() {
markAllBtn.disabled = false;
showToast(i18n.networkError || '网络错误');
});
});
}
// 批量已读
if (markSelectedBtn) {
markSelectedBtn.addEventListener('click', function() {
var checked = Array.prototype.slice.call(list.querySelectorAll('.aksrt-notification-check:checked')).map(function(input) {
return input.value;
});
if (!checked.length) {
showToast(i18n.selectNotifications || '请先选择要标记的通知');
return;
}
markSelectedBtn.disabled = true;
var chain = Promise.resolve();
checked.forEach(function(id) {
chain = chain.then(function() { return markRead(id, false); });
});
chain.then(function() {
checked.forEach(function(id) {
var row = list.querySelector('[data-notification-id="' + id + '"]');
if (row) row.classList.add('is-read');
var b = row ? row.querySelector('.aksrt-notification-read-btn') : null;
if (b) b.remove();
});
showToast(i18n.selectedMarkedRead || '已标记所选通知为已读');
markSelectedBtn.disabled = false;
}).catch(function() {
markSelectedBtn.disabled = false;
showToast(i18n.networkError || '网络错误');
});
});
}
// 批量删除
if (deleteSelectedBtn) {
deleteSelectedBtn.addEventListener('click', function() {
var checked = Array.prototype.slice.call(list.querySelectorAll('.aksrt-notification-check:checked')).map(function(input) {
return input.value;
});
if (!checked.length) {
showToast(i18n.selectNotifications || '请先选择要删除的通知');
return;
}
if (!confirm(i18n.confirmBatchDelete || '确定批量删除所选通知?')) return;
deleteSelectedBtn.disabled = true;
var body = new FormData();
body.append('action', 'aksrt_delete_notifications');
body.append('nonce', publicNonce);
checked.forEach(function(id) {
body.append('notification_ids[]', id);
});
fetch(ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
.then(function(r) { return r.json(); })
.then(function(res) {
if (res && res.success) {
checked.forEach(function(id) {
var row = list.querySelector('[data-notification-id="' + id + '"]');
if (row) row.remove();
});
showToast(i18n.batchDeleted || '已删除所选通知');
} else {
deleteSelectedBtn.disabled = false;
showToast((res && res.data && res.data.message) || (i18n.operationFailed || '操作失败'));
}
})
.catch(function() {
deleteSelectedBtn.disabled = false;
showToast(i18n.networkError || '网络错误');
});
});
}
}
/* ==================== 账号设置:弹窗 / 密码 / 邮箱 / 绑定 ==================== */
function initSettings() {
if (!ajaxUrl || !settingsNonce) return;
function openModal(id) {
var m = document.getElementById(id);
if (!m) return;
m.classList.add('is-open');
document.body.style.overflow = 'hidden';
var firstInput = m.querySelector('input:not([type=hidden])');
if (firstInput) setTimeout(function() { firstInput.focus(); }, 200);
}
function closeModal(m) {
if (typeof m === 'string') m = document.getElementById(m);
if (!m) return;
m.classList.remove('is-open');
document.body.style.overflow = '';
var f = m.querySelector('form');
var sceneMap = { 'pwd-modal': 'change_password', 'email-modal': 'change_email', 'phone-modal': 'bind_phone' };
var scene = m.id && sceneMap[m.id] ? sceneMap[m.id] : '';
var store = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes ? window.AKSRTCaptchaState.scenes : null;
if (f) {
f.reset();
var bar = document.getElementById('pwd-strength-bar');
var txt = document.getElementById('pwd-strength-text');
if (bar && bar.firstChild) { bar.style.width = '0'; bar.firstChild.className = 'pwd-strength__fill'; }
if (txt) { txt.textContent = ''; txt.className = 'pwd-strength__text'; }
}
if (scene && store && store[scene] && typeof store[scene].reset === 'function') {
store[scene].reset();
}
}
document.querySelectorAll('.security-trigger').forEach(function(btn) {
btn.addEventListener('click', function() { openModal(this.getAttribute('data-modal')); });
});
document.querySelectorAll('[data-close-modal]').forEach(function(el) {
el.addEventListener('click', function() { closeModal(this.closest('.aksrt-modal')); });
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
var openM = document.querySelector('.aksrt-modal.is-open');
if (openM) closeModal(openM);
}
});
// 密码显隐切换
document.querySelectorAll('#pwd-modal .toggle-pwd, #email-modal .toggle-pwd').forEach(function(btn) {
btn.addEventListener('click', function() {
var inp = document.getElementById(this.getAttribute('data-target'));
if (!inp) return;
inp.type = (inp.type === 'password') ? 'text' : 'password';
this.classList.toggle('is-visible');
});
});
// 密码强度
var pInput = document.getElementById('pwd-new');
var sBar = document.getElementById('pwd-strength-bar');
var sTxt = document.getElementById('pwd-strength-text');
if (pInput && sBar && sTxt) {
pInput.addEventListener('input', function() {
var v = this.value;
var f = sBar.querySelector('.pwd-strength__fill');
if (!v) { f.className = 'pwd-strength__fill'; sTxt.className = 'pwd-strength__text'; sTxt.textContent = ''; return; }
var s = 0;
if (v.length >= 6) s++;
if (v.length >= 10) s++;
if (/[a-z]/.test(v) && /[A-Z]/.test(v)) s++;
if (/\d/.test(v)) s++;
if (/[^a-zA-Z0-9]/.test(v)) s++;
var lv = '', tx = '';
if (s <= 1) { lv = 'weak'; tx = '弱'; }
else if (s <= 3) { lv = 'medium'; tx = '中'; }
else { lv = 'strong'; tx = '强'; }
f.className = 'pwd-strength__fill level-' + lv;
sTxt.className = 'pwd-strength__text level-' + lv;
sTxt.textContent = '密码强度: ' + tx;
});
}
// 验证码发送
function triggerSceneCaptcha(scene, callback) {
var store = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes ? window.AKSRTCaptchaState.scenes : null;
var instance = store && store[scene] ? store[scene] : null;
if (instance && typeof instance.verify === 'function') {
instance.verify(callback);
return;
}
callback();
}
function getSendBtnIdleText(btnId) {
if (btnId === 'pwd-send-code') return i18n.sendToCurrentEmail || '发送到当前邮箱';
if (btnId === 'email-send-code') return i18n.sendToNewEmail || '发送到新邮箱';
return i18n.sendCode || '发送验证码';
}
function bindSend(btnId, formId, scene) {
var b = document.getElementById(btnId);
if (!b) return;
b.addEventListener('click', function() {
if (this.classList.contains('is-counting')) return;
var self = this;
var form = document.getElementById(formId);
triggerSceneCaptcha(scene, function() {
self.disabled = true;
self.textContent = i18n.sending || '发送中...';
var data = new URLSearchParams();
data.set('action', 'aksrt_send_email_code');
data.set('_settings_nonce', settingsNonce);
data.set('scene', scene || '');
if (form) {
new FormData(form).forEach(function(value, key) {
if (data.has(key) || value === '' || value == null) return;
data.set(key, value);
});
}
fetch(ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: data.toString() })
.then(function(r) { return r.json(); }).then(function(res) {
if (res.success) {
showToast(res.data.message || (i18n.codeSent || '验证码已发送'));
var sec = 60;
self.classList.add('is-counting');
self.textContent = sec + 's 后重发';
var t = setInterval(function() {
sec--;
if (sec <= 0) {
clearInterval(t);
self.disabled = false;
self.classList.remove('is-counting');
self.textContent = getSendBtnIdleText(btnId);
} else {
self.textContent = sec + 's 后重发';
}
}, 1000);
} else {
showToast(res.data.message || (i18n.sendFailed || '发送失败'));
self.disabled = false;
self.textContent = getSendBtnIdleText(btnId);
}
})
.catch(function() {
showToast(i18n.networkError || '网络错误');
self.disabled = false;
self.textContent = getSendBtnIdleText(btnId);
});
});
});
}
bindSend('pwd-send-code', 'pwd-form', 'change_password');
bindSend('email-send-code', 'email-form', 'change_email');
// 表单提交
function submitForm(fid, act) {
var fm = document.getElementById(fid);
if (!fm) return;
fm.addEventListener('submit', function(e) {
e.preventDefault();
var btn = fm.querySelector('[type=submit]');
var orig = btn ? btn.textContent : '';
var reqs = fm.querySelectorAll('[required]');
for (var i = 0; i < reqs.length; i++) {
if (!reqs[i].value.trim()) { reqs[i].focus(); showToast(i18n.fillRequired || '请填写必填项'); return; }
}
if (fid === 'pwd-form') {
var pwdNew = document.getElementById('pwd-new');
var pwdConfirm = document.getElementById('pwd-new-confirm');
if (pwdNew && pwdConfirm && pwdNew.value !== pwdConfirm.value) {
pwdConfirm.focus();
showToast(i18n.passwordMismatch || '两次输入的新密码不一致');
return;
}
}
if (btn) { btn.disabled = true; btn.textContent = i18n.submitting || '提交中...'; }
var d = new FormData(fm);
d.append('action', act);
d.append('_settings_nonce', settingsNonce);
fetch(ajaxUrl, { method: 'POST', body: d })
.then(function(r) { return r.json(); })
.then(function(r) {
if (btn) { btn.disabled = false; btn.textContent = orig; }
if (r.success) {
showToast(r.data.message || '');
closeModal(fm.closest('.aksrt-modal'));
if (r.data.redirect_to) setTimeout(function() { window.location.href = r.data.redirect_to; }, 2500);
} else {
showToast(r.data.message || (i18n.operationFailed || '操作失败'));
}
})
.catch(function() {
if (btn) { btn.disabled = false; btn.textContent = orig; }
showToast(i18n.networkError || '网络错误');
});
});
}
submitForm('pwd-form', 'aksrt_change_password');
submitForm('email-form', 'aksrt_change_email');
// 解绑
document.querySelectorAll('.binding-unbind-btn').forEach(function(b) {
b.addEventListener('click', function() {
var p = this.getAttribute('data-provider');
if (!p) return;
if (!confirm(i18n.confirmUnbind || '确定解除绑定?')) return;
var self = b;
self.disabled = true;
self.textContent = i18n.unbinding || '解除中...';
var unbindNonce = document.getElementById('aksrt-oauth-unbind-nonce');
var data = new URLSearchParams();
data.set('action', 'aksrt_oauth_unbind');
data.set('nonce', unbindNonce ? unbindNonce.value : '');
data.set('provider', p);
data.set('userId', String(userId));
fetch(ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: data.toString()
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.success) {
showToast(i18n.unbindSuccess || '解除成功');
setTimeout(function() {
var u = new URL(window.location);
u.searchParams.set('tab', 'settings');
u.searchParams.set('oauth_unbound', p);
window.location.href = u.toString();
}, 1000);
} else {
showToast(i18n.unbindFailed || '解除失败');
self.disabled = false;
self.textContent = i18n.unbind || '解除';
}
})
.catch(function() {
showToast(i18n.networkError || '网络错误');
self.disabled = false;
self.textContent = i18n.unbind || '解除';
});
});
});
}
/* ==================== 初始化 ==================== */
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
initDashboardNavigation();
initProfileForm();
initAuthForm();
initUnfavorite();
initNotifications();
initSettings();
});
} else {
initDashboardNavigation();
initProfileForm();
initAuthForm();
initUnfavorite();
initNotifications();
initSettings();
}
// 绑定手机
(function initBindPhone() {
var form = document.getElementById('aksrt-bind-phone-form');
if (!form) return;
form.addEventListener('submit', function (e) {
e.preventDefault();
var phoneEl = form.querySelector('[name="phone"]');
var codeEl = form.querySelector('[name="code"]');
var phone = phoneEl ? String(phoneEl.value || '').trim() : '';
var code = codeEl ? String(codeEl.value || '').trim() : '';
if (!/^1[3-9]\d{9}$/.test(phone)) {
showToast('请输入正确的手机号');
return;
}
if (!code) {
showToast('请输入短信验证码');
return;
}
var submitBtn = form.querySelector('[type="submit"]');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.textContent = '绑定中...';
}
function collectCaptcha(formEl) {
var out = {};
[
'captcha_verified', 'tencent_ticket', 'tencent_randstr', 'tencent_sid',
'cf_turnstile_response', 'geetest_lot_number', 'geetest_captcha_output',
'geetest_pass_token', 'geetest_gen_time', 'aliyun_captcha_verify_param'
].forEach(function (name) {
var el = formEl.querySelector('[name="' + name + '"]');
if (el && el.value) out[name] = el.value;
});
return out;
}
function resetCaptcha() {
try {
var store = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes;
if (store && store.bind_phone && typeof store.bind_phone.reset === 'function') {
store.bind_phone.reset();
}
} catch (err) {}
}
function doBind() {
var captcha = collectCaptcha(form);
var restRoot = (window.aksrtData && aksrtData.apiUrl) || '/wp-json/aksrt/v1';
var nonce = (window.aksrtData && aksrtData.restNonce) || '';
fetch(String(restRoot).replace(/\/$/, '') + '/auth/bind-phone', {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': nonce
},
body: JSON.stringify(Object.assign({ phone: phone, code: code }, captcha))
})
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, json: j }; }); })
.then(function (res) {
if (res.ok && res.json && res.json.success) {
showToast((res.json.message) || '绑定成功');
setTimeout(function () { window.location.reload(); }, 600);
return;
}
resetCaptcha();
showToast((res.json && (res.json.message || res.json.error)) || '绑定失败');
if (submitBtn) {
submitBtn.disabled = false;
submitBtn.textContent = '确认绑定';
}
})
.catch(function () {
resetCaptcha();
showToast('网络错误');
if (submitBtn) {
submitBtn.disabled = false;
submitBtn.textContent = '确认绑定';
}
});
}
var store = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes;
if (store && store.bind_phone && typeof store.bind_phone.verify === 'function') {
store.bind_phone.verify(doBind);
} else {
doBind();
}
});
})();
})();