/** * Jio Follow — 前台关注交互 * * @package Jio */ (function () { 'use strict'; var CONFIG = window.jioData || {}; var API_ROOT = (function () { var raw = CONFIG.apiUrl || CONFIG.restUrl || CONFIG.rest_url || '/index.php?rest_route=/jio/v1'; return String(raw).replace(/\/$/, ''); })(); var NONCE = CONFIG.restNonce || ''; function buttonsFor(userId) { return Array.prototype.slice.call(document.querySelectorAll('[data-jio-follow="' + userId + '"]')); } function notify(message, type) { if (typeof window.notyf !== 'function') return; window.notyf(message, type || 'info'); } /** 站点登录弹窗由 auth.js 的全局委托接管,这里只点一下触发器。 */ function openLoginModal() { var trigger = document.querySelector('.signin-loader') || document.querySelector('[data-jio-auth-required]') || document.querySelector('#nav-login-btn'); if (trigger) trigger.click(); } /** 待发送态:按钮置灰不可重复提交,文案换成行内加载点。 */ function setPending(button, pending) { var label = button.querySelector('[data-jio-follow-label]'); if (pending) { button.setAttribute('disabled', ''); button.setAttribute('aria-disabled', 'true'); if (label) { label.dataset.jioFollowLabel = label.textContent; label.innerHTML = ''; } return; } button.removeAttribute('disabled'); button.removeAttribute('aria-disabled'); if (label && label.dataset.jioFollowLabel !== undefined) { label.textContent = label.dataset.jioFollowLabel; delete label.dataset.jioFollowLabel; } } function updateButton(button, isFollowing) { var label = button.querySelector('[data-jio-follow-label]'); if (!label) return; button.classList.toggle('actived', isFollowing); var icon = button.querySelector('i'); if (icon) { var sizeClass = /\bem09\b/.test(icon.className) ? ' em09' : ''; icon.className = (isFollowing ? 'fa fas fa-heart' : 'fa far fa-heart') + sizeClass; } label.textContent = isFollowing ? button.getAttribute('data-jio-follow-ok') || '已关注' : button.getAttribute('data-jio-follow-text') || '关注'; delete label.dataset.jioFollowLabel; button.title = isFollowing ? '点击取消关注' : '关注该用户'; } /** 关注数只在浏览被关注者本人的主页时同步,避免改到别人的粉丝数。 */ function updateFollowerCount(targetUserId, count) { if (count === undefined || count === null) return; var scope = document.querySelector('.dashboard[data-user-id="' + targetUserId + '"]'); if (!scope) return; scope.querySelectorAll('[data-follow-count="followers"]').forEach(function (node) { node.textContent = count; }); } document.addEventListener('click', function (event) { var button = event.target.closest('[data-jio-follow]'); if (!button) return; event.preventDefault(); var targetUserId = parseInt(button.getAttribute('data-jio-follow'), 10); if (!targetUserId || button.hasAttribute('disabled')) return; var matchingButtons = buttonsFor(targetUserId); matchingButtons.forEach(function (matchingButton) { setPending(matchingButton, true); }); fetch(API_ROOT + '/follow/toggle', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': NONCE, }, body: JSON.stringify({ target_user_id: targetUserId }), }) .then(function (response) { // 会话失效时直接拉起登录弹窗,不再额外弹错误提示。 if (response.status === 401 || response.status === 403) { openLoginModal(); return null; } return response.json().catch(function () { throw new Error('操作失败'); }); }) .then(function (result) { if (!result) return; if (!result.success || !result.data) { notify(result.message || '操作失败', 'danger'); return; } var isFollowing = Boolean(result.data.is_following); matchingButtons.forEach(function (matchingButton) { updateButton(matchingButton, isFollowing); }); updateFollowerCount(targetUserId, result.data.follower_count); if (!isFollowing) { var managementItem = button.closest('.uc-follow-management__item'); if (managementItem) managementItem.remove(); } notify(isFollowing ? '已关注此用户' : '已取消关注此用户', 'success'); }) .catch(function (error) { notify((error && error.message) || '网络错误,请重试', 'danger'); }) .finally(function () { matchingButtons.forEach(function (matchingButton) { setPending(matchingButton, false); }); }); }); })();