diff --git a/assets/css/frontend/nav/header-userbox.css b/assets/css/frontend/nav/header-userbox.css new file mode 100644 index 00000000..9db422c2 --- /dev/null +++ b/assets/css/frontend/nav/header-userbox.css @@ -0,0 +1,96 @@ +/** + * Header user-box density (check-in / wallet / payvip / signout modal). + * + * @package AKSRT + */ + +.aksrt-header-wallet { + display: flex; + gap: 10px; + justify-content: space-between; + padding: 8px 10px; + border-radius: 8px; + background: var(--surface-2, rgba(0, 0, 0, 0.04)); + color: inherit; + text-decoration: none; + font-size: 12px; +} + +.aksrt-header-wallet__item b { + margin-left: 2px; +} + +.aksrt-header-checkin { + width: 100%; + border: 0; + border-radius: 6px; + padding: 8px 10px; + cursor: pointer; + background: rgba(255, 193, 7, 0.18); + color: #b78103; +} + +.aksrt-header-checkin.is-done { + opacity: 0.75; + cursor: default; +} + +.aksrt-header-payvip .payvip-icon, +.aksrt-header-payvip .but { + display: block; + text-align: center; + text-decoration: none; + padding: 8px 10px; + border-radius: 6px; + background: linear-gradient(90deg, #ff6b6b, #f04494); + color: #fff; +} + +.aksrt-header-badges { + flex-wrap: wrap; + gap: 4px; +} + +#modal_signout.modal { + position: fixed; + inset: 0; + z-index: 1100; + display: none; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.45); + padding: 16px; +} + +#modal_signout.modal.is-open, +#modal_signout.modal.show { + display: flex; +} + +#modal_signout .modal-content { + background: var(--main-bg-color, #fff); + border-radius: 10px; + min-width: 280px; + max-width: 92vw; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18); +} + +#modal_signout .but.c-red { + background: #e74c3c; + color: #fff; + text-decoration: none; + padding: 8px 14px; + border-radius: 6px; +} + +#modal_signout .but { + border: 0; + background: var(--surface-2, #f0f0f0); + padding: 8px 14px; + border-radius: 6px; + cursor: pointer; +} + +.user-dropdown .social_loginbar { + padding: 0 10px 12px; +} diff --git a/assets/js/header-userbox.js b/assets/js/header-userbox.js new file mode 100644 index 00000000..12f20529 --- /dev/null +++ b/assets/js/header-userbox.js @@ -0,0 +1,113 @@ +/** + * Header user-box: check-in REST + signout modal. + * + * @package AKSRT + */ +(function () { + 'use strict'; + + function restBase() { + if (window.aksrtData && window.aksrtData.restUrl) return window.aksrtData.restUrl.replace(/\/?$/, '/'); + if (window.aksrtData && window.aksrtData.siteUrl) return String(window.aksrtData.siteUrl).replace(/\/?$/, '/') + 'wp-json/'; + return '/wp-json/'; + } + + function restNonce() { + return (window.aksrtData && window.aksrtData.restNonce) || ''; + } + + function toast(msg, type) { + if (window.aksrt && typeof window.aksrt.toast === 'function') { + window.aksrt.toast(msg, type || 'info'); + return; + } + // eslint-disable-next-line no-alert + window.alert(msg); + } + + function openModal(id) { + var modal = document.getElementById(id); + if (!modal) return; + modal.classList.add('is-open', 'show'); + modal.setAttribute('aria-hidden', 'false'); + } + + function closeModal(id) { + var modal = document.getElementById(id); + if (!modal) return; + modal.classList.remove('is-open', 'show'); + modal.setAttribute('aria-hidden', 'true'); + } + + function initSignoutModal() { + document.addEventListener('click', function (e) { + var openBtn = e.target.closest('[data-target="#modal_signout"], [href="#modal_signout"]'); + if (openBtn) { + e.preventDefault(); + openModal('modal_signout'); + return; + } + var dismiss = e.target.closest('#modal_signout [data-dismiss="modal"]'); + if (dismiss) { + e.preventDefault(); + closeModal('modal_signout'); + return; + } + if (e.target && e.target.id === 'modal_signout') { + closeModal('modal_signout'); + } + }); + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape') closeModal('modal_signout'); + }); + } + + function initCheckin() { + document.addEventListener('click', function (e) { + var btn = e.target.closest('[data-aksrt-checkin="1"]'); + if (!btn || btn.disabled) return; + e.preventDefault(); + btn.disabled = true; + fetch(restBase() + 'aksrt/v1/signin', { + method: 'POST', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + 'X-WP-Nonce': restNonce(), + }, + body: '{}', + }) + .then(function (r) { + return r.json().then(function (data) { + return { ok: r.ok, data: data }; + }); + }) + .then(function (res) { + if (!res.ok) { + var msg = (res.data && (res.data.message || res.data.msg)) || '签到失败'; + toast(msg, 'danger'); + btn.disabled = false; + return; + } + toast((res.data && res.data.message) || '签到成功', 'success'); + btn.classList.add('is-done'); + btn.innerHTML = ' 今日已签到'; + }) + .catch(function () { + toast('网络错误', 'danger'); + btn.disabled = false; + }); + }); + } + + function init() { + initSignoutModal(); + initCheckin(); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); diff --git a/header.php b/header.php index 115573c1..628799c9 100644 --- a/header.php +++ b/header.php @@ -303,11 +303,32 @@ if (!empty($aksrt_bg_styles)) { + ' . $checkin . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + } + if (function_exists('aksrt_header_user_wallet_mini')) { + echo '