Files
wordpress-theme-aksrt/assets/js/widget-set.js
T
kate522 0e8c9d12c7 feat(widgets): plate moderator apply modal + JS submit
Replace bare apply link with modal form posting to forum moderator
REST; empty/admin states and modal CSS.
2026-07-21 14:36:00 +08:00

521 lines
20 KiB
JavaScript

/**
* AKSRT Widget Set
*
* Handles widget-local interactions and floating QR widgets.
*
* @package AKSRT
*/
(function () {
'use strict';
function restHeaders() {
var headers = { Accept: 'application/json' };
if (window.aksrtData && aksrtData.restNonce) {
headers['X-WP-Nonce'] = aksrtData.restNonce;
}
return headers;
}
function initWidgetTabs() {
document.querySelectorAll('.widget-tab-posts[data-aksrt-tab-posts]').forEach(function (widget) {
if (widget.dataset.aksrtWidgetTabsBound === '1') return;
widget.dataset.aksrtWidgetTabsBound = '1';
var tabs = widget.querySelectorAll('.widget-tab-posts__tab');
var panels = widget.querySelectorAll('.widget-tab-posts__panel');
if (!tabs.length || !panels.length) return;
var rest = widget.getAttribute('data-rest') || '';
var defaultCount = widget.getAttribute('data-count') || '5';
function loadPanel(panel, tab) {
if (!panel || panel.getAttribute('data-loaded') === '1' || !rest) return;
var orderby = tab.getAttribute('data-orderby') || 'date';
var cat = tab.getAttribute('data-cat') || '0';
var tabCount = tab.getAttribute('data-tab-count') || '0';
var style = widget.getAttribute('data-style') || 'mini';
var paginate = widget.getAttribute('data-paginate') || 'none';
var qs = new URLSearchParams({
count: defaultCount,
orderby: orderby,
cat: cat,
tab_count: tabCount,
style: style,
paginate: paginate,
topics: tab.getAttribute('data-topics') || '',
limit_day: tab.getAttribute('data-limit-day') || '0',
pay_type: tab.getAttribute('data-pay-type') || '',
});
var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + qs.toString();
panel.classList.add('is-ajax-loading');
fetch(url, { credentials: 'same-origin', headers: restHeaders() })
.then(function (r) { return r.json(); })
.then(function (j) {
var d = (j && j.data) || j || {};
var html = d.html || '';
var pag = d.paginate_html || d.paginateHtml || '';
panel.innerHTML = (html || '<p class="widget-empty">暂无文章</p>') + (pag || '');
panel.setAttribute('data-loaded', '1');
panel.classList.remove('is-ajax-loading');
})
.catch(function () {
panel.classList.remove('is-ajax-loading');
});
}
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
var target = tab.getAttribute('data-tab');
tabs.forEach(function (item) {
var active = item === tab;
item.classList.toggle('active', active);
item.classList.toggle('is-active', active);
item.setAttribute('aria-selected', active ? 'true' : 'false');
});
panels.forEach(function (panel) {
var active = panel.getAttribute('data-tab-panel') === target;
panel.classList.toggle('active', active);
panel.classList.toggle('is-active', active);
if (active) {
panel.removeAttribute('hidden');
loadPanel(panel, tab);
} else {
panel.setAttribute('hidden', '');
}
});
});
});
});
}
// Homepage category tabs (was inline in CategoryTabsWidget).
function initCategoryTabs() {
document.querySelectorAll('[data-aksrt-home-cat-tabs]').forEach(function (section) {
if (section.dataset.aksrtCatTabsBound === '1') return;
section.dataset.aksrtCatTabsBound = '1';
var rest = section.getAttribute('data-rest') || '';
var count = section.getAttribute('data-count') || '6';
var layout = section.getAttribute('data-layout') || 'card';
var columns = section.getAttribute('data-columns') || '3';
var context = section.getAttribute('data-context') || 'homepage';
var showMore = section.getAttribute('data-show-more') === '1';
var tabs = [].slice.call(section.querySelectorAll('.widget-tab-posts__tab'));
var panels = [].slice.call(section.querySelectorAll('.widget-tab-posts__panel'));
if (!tabs.length || !panels.length || !rest) return;
function load(panel) {
if (!panel || panel.getAttribute('data-loaded') === '1') return;
var cat = panel.getAttribute('data-cat') || '0';
var more = panel.getAttribute('data-more') || '';
var qs = new URLSearchParams({
cat: cat,
count: String(count),
layout: layout,
columns: String(columns),
context: context,
});
var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + qs.toString();
panel.classList.add('is-ajax-loading');
fetch(url, { credentials: 'same-origin', headers: restHeaders() })
.then(function (r) { return r.json(); })
.then(function (j) {
var d = (j && j.data) || j || {};
var html = d.html || '';
if (showMore && more) {
html += '<div class="aksrt-home-widget__footer"><a class="aksrt-home-widget__more" href="' + more + '">查看更多</a></div>';
}
panel.innerHTML = html || '<div class="ajax-item widget-empty muted-2-color">暂无文章</div>';
panel.setAttribute('data-loaded', '1');
panel.classList.remove('is-ajax-loading');
})
.catch(function () {
panel.classList.remove('is-ajax-loading');
});
}
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
var target = tab.getAttribute('data-tab');
tabs.forEach(function (item) {
var active = item === tab;
item.classList.toggle('active', active);
item.setAttribute('aria-selected', active ? 'true' : 'false');
});
panels.forEach(function (panel) {
var active = panel.getAttribute('data-tab-panel') === target;
panel.classList.toggle('active', active);
if (active) {
panel.removeAttribute('hidden');
load(panel);
} else {
panel.setAttribute('hidden', '');
}
});
});
});
});
}
// Forum multi-tab topics.
function initForumTabTopics() {
document.querySelectorAll('.aksrt-ftab[data-aksrt-ftab]').forEach(function (root) {
if (root.dataset.aksrtFtabBound === '1') return;
root.dataset.aksrtFtabBound = '1';
var rest = root.getAttribute('data-rest') || '';
var count = root.getAttribute('data-count') || '6';
var style = root.getAttribute('data-style') || 'mini';
var plate = root.getAttribute('data-plate') || '0';
var btns = [].slice.call(root.querySelectorAll('.aksrt-ftab__btn'));
var panels = [].slice.call(root.querySelectorAll('.aksrt-ftab__panel'));
function load(panel, orderby) {
if (!panel || panel.getAttribute('data-loaded') === '1' || !rest) return;
var qs = new URLSearchParams({
page: '1',
count: count,
orderby: orderby || 'date',
style: style,
plate: plate,
period: 'all',
paginate: 'none',
});
var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + qs.toString();
panel.classList.add('is-ajax-loading');
fetch(url, { credentials: 'same-origin', headers: restHeaders() })
.then(function (r) { return r.json(); })
.then(function (j) {
var d = (j && j.data) || j || {};
var html = d.html || '';
panel.innerHTML = html || '<div class="ajax-item aksrt-ftab__empty muted-2-color">暂无内容</div>';
panel.setAttribute('data-loaded', '1');
panel.classList.remove('is-ajax-loading');
})
.catch(function () {
panel.classList.remove('is-ajax-loading');
});
}
function go(i) {
btns.forEach(function (b, idx) {
var on = idx === i;
b.classList.toggle('is-active', on);
b.setAttribute('aria-selected', on ? 'true' : 'false');
});
panels.forEach(function (p, idx) {
var on = idx === i;
p.classList.toggle('is-active', on);
if (on) {
p.removeAttribute('hidden');
} else {
p.setAttribute('hidden', '');
}
});
var btn = btns[i];
var panel = panels[i];
if (btn && panel) load(panel, btn.getAttribute('data-orderby') || 'date');
}
btns.forEach(function (b) {
b.addEventListener('click', function () {
go(parseInt(b.getAttribute('data-index') || '0', 10));
});
});
});
}
// Product multi-tab.
function initProductTabs() {
document.querySelectorAll('[data-aksrt-product-tab]').forEach(function (root) {
if (root.dataset.aksrtProductTabBound === '1') return;
root.dataset.aksrtProductTabBound = '1';
var rest = root.getAttribute('data-rest') || '';
var per = root.getAttribute('data-per-page') || '8';
var style = root.getAttribute('data-style') || 'default';
var paginate = root.getAttribute('data-paginate') || 'ajax';
function skeleton(n) {
n = Math.max(1, Math.min(12, parseInt(n, 10) || 4));
var html = '<div class="aksrt-product-tab__skeleton">';
for (var i = 0; i < n; i++) {
html += '<div class="placeholder-row product-card-placeholder"><div class="placeholder thumb"></div><div class="placeholder k1"></div><div class="placeholder s1"></div></div>';
}
return html + '</div>';
}
function loadPanel(panel, btn) {
if (!panel || panel.getAttribute('data-loaded') === '1' || !rest) return;
var grid = panel.querySelector('[data-aksrt-ajaxpager]');
if (!grid) return;
var qs = new URLSearchParams({
page: '1',
per_page: per,
style: style,
paginate: paginate,
orderby: btn.getAttribute('data-orderby') || 'date',
order: 'DESC',
cat_ids: btn.getAttribute('data-cat-ids') || '',
tag_ids: btn.getAttribute('data-tag-ids') || '',
discount_ids: btn.getAttribute('data-discount-ids') || '',
});
var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + qs.toString();
grid.classList.add('is-ajax-loading');
if (!grid.querySelector('.aksrt-product-tab__skeleton') && !grid.querySelector('.ajax-item')) {
grid.insertAdjacentHTML('afterbegin', skeleton(per));
}
fetch(url, { credentials: 'same-origin', headers: restHeaders() })
.then(function (r) { return r.json(); })
.then(function (j) {
var d = (j && j.data && (j.data.data || j.data)) || j || {};
var html = d.html || '';
var pag = d.paginate_html || d.paginateHtml || '';
var loader = grid.querySelector('[data-aksrt-ajax-loader]');
grid.innerHTML = '';
if (html) grid.insertAdjacentHTML('beforeend', html);
else grid.insertAdjacentHTML('beforeend', '<p class="widget-empty ajax-item">暂无商品</p>');
if (pag) grid.insertAdjacentHTML('beforeend', pag);
if (loader) grid.appendChild(loader);
panel.setAttribute('data-loaded', '1');
grid.classList.remove('is-ajax-loading');
})
.catch(function () {
grid.classList.remove('is-ajax-loading');
});
}
root.querySelectorAll('.aksrt-product-tab__header').forEach(function (btn) {
btn.addEventListener('click', function () {
root.querySelectorAll('.aksrt-product-tab__header').forEach(function (b) {
b.classList.remove('is-active');
});
root.querySelectorAll('.aksrt-product-tab__panel').forEach(function (p) {
p.style.display = 'none';
p.classList.remove('is-active');
});
btn.classList.add('is-active');
var idx = btn.getAttribute('data-tab-index');
var panel = root.querySelector('.aksrt-product-tab__panel[data-tab-index="' + idx + '"]');
if (panel) {
panel.style.display = '';
panel.classList.add('is-active');
loadPanel(panel, btn);
}
});
});
});
}
// Main posts load_mode=ajax first paint.
function initMainPostsLazy() {
document.querySelectorAll('.aksrt-main-posts[data-load-mode="ajax"]').forEach(function (root) {
if (root.dataset.aksrtMainLazyBound === '1') return;
root.dataset.aksrtMainLazyBound = '1';
if (root.getAttribute('data-loaded') === '1') return;
var rest = root.getAttribute('data-aksrt-ajax-url') || root.getAttribute('data-rest') || '';
if (!rest) return;
var qs = root.getAttribute('data-query') || '';
var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + (qs || 'page=1');
root.classList.add('is-ajax-loading');
fetch(url, { credentials: 'same-origin', headers: restHeaders() })
.then(function (r) { return r.json(); })
.then(function (j) {
var d = (j && j.data) || j || {};
var html = d.html || '';
var pag = d.paginate_html || d.paginateHtml || '';
var loader = root.querySelector('[data-aksrt-ajax-loader]');
// Remove skeleton rows.
root.querySelectorAll('.aksrt-main-posts__skeleton, .posts-mini.placeholder-row, .placeholder-row').forEach(function (n) {
n.remove();
});
if (html) {
root.insertAdjacentHTML('afterbegin', html);
} else {
root.insertAdjacentHTML('afterbegin', '<p class="widget-empty ajax-item">暂无文章</p>');
}
// Replace/append paginate.
var oldPag = root.querySelector('.ajax-pag, .pagenav.ajax-pag');
if (oldPag) oldPag.remove();
if (pag) {
if (loader) loader.insertAdjacentHTML('beforebegin', pag);
else root.insertAdjacentHTML('beforeend', pag);
}
root.setAttribute('data-loaded', '1');
root.classList.remove('is-ajax-loading');
})
.catch(function () {
root.classList.remove('is-ajax-loading');
});
});
}
// Feature intro media tabs.
function initFeatureIntro() {
document.querySelectorAll('[data-aksrt-feature-intro]').forEach(function (root) {
if (root.dataset.aksrtFiBound === '1') return;
root.dataset.aksrtFiBound = '1';
var tabs = [].slice.call(root.querySelectorAll('.aksrt-fi__tab'));
var panels = [].slice.call(root.querySelectorAll('.aksrt-fi__panel'));
if (!tabs.length || !panels.length) return;
function go(i) {
tabs.forEach(function (t, idx) {
t.classList.toggle('is-active', idx === i);
});
panels.forEach(function (p, idx) {
p.classList.toggle('is-active', idx === i);
var v = p.querySelector('video');
if (!v) return;
if (idx === i) {
if (!v.getAttribute('src') && v.getAttribute('data-src')) {
v.setAttribute('src', v.getAttribute('data-src'));
}
if (v.play) v.play().catch(function () {});
} else if (v.pause) {
v.pause();
}
});
}
tabs.forEach(function (t) {
t.addEventListener('click', function () {
go(parseInt(t.getAttribute('data-index') || '0', 10));
});
});
});
}
function initModeratorApplyModal() {
document.addEventListener('click', function (e) {
var openBtn = e.target.closest('[data-aksrt-mod-apply-open]');
if (openBtn) {
e.preventDefault();
var id = openBtn.getAttribute('data-aksrt-mod-apply-open');
var modal = id ? document.getElementById(id) : null;
if (modal) {
modal.hidden = false;
document.body.classList.add('aksrt-mod-apply-open');
}
return;
}
var closeBtn = e.target.closest('[data-aksrt-mod-apply-close]');
if (closeBtn) {
var box = closeBtn.closest('.aksrt-mod-apply-modal');
if (box) {
box.hidden = true;
document.body.classList.remove('aksrt-mod-apply-open');
}
}
});
document.querySelectorAll('.js-aksrt-moderator-apply-form').forEach(function (form) {
if (form.dataset.aksrtModApplyBound === '1') return;
form.dataset.aksrtModApplyBound = '1';
form.addEventListener('submit', function (event) {
event.preventDefault();
var boardId = parseInt(form.getAttribute('data-board-id') || '0', 10);
var reasonField = form.querySelector('[name="reason"]');
var reason = reasonField ? reasonField.value.trim() : '';
var feedback = form.querySelector('.js-aksrt-action-feedback');
var submitButton = form.querySelector('button[type="submit"]');
if (!boardId || !reason) {
if (feedback) {
feedback.textContent = '请填写完整的申请理由。';
feedback.className = 'js-aksrt-action-feedback mb10 is-error';
}
return;
}
if (submitButton) submitButton.disabled = true;
if (feedback) {
feedback.textContent = '正在提交申请…';
feedback.className = 'js-aksrt-action-feedback mb10 is-loading';
}
var siteUrl = (window.aksrtData && aksrtData.siteUrl) ? String(aksrtData.siteUrl).replace(/\/+$/, '') : '';
var url = siteUrl + '/wp-json/aksrt/v1/forum/moderator/apply';
fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-WP-Nonce': (window.aksrtData && aksrtData.restNonce) || '',
},
body: JSON.stringify({ board_id: boardId, reason: reason }),
})
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
.then(function (res) {
if (!res.ok || (res.j && res.j.success === false)) {
throw new Error((res.j && res.j.message) || '申请提交失败');
}
var msg = (res.j && (res.j.message || (res.j.data && res.j.data.message))) || '申请已提交';
if (feedback) {
feedback.textContent = msg;
feedback.className = 'js-aksrt-action-feedback mb10 is-success';
}
if (reasonField) reasonField.disabled = true;
})
.catch(function (err) {
if (feedback) {
feedback.textContent = (err && err.message) || '申请提交失败。';
feedback.className = 'js-aksrt-action-feedback mb10 is-error';
}
if (submitButton) submitButton.disabled = false;
});
});
});
}
function initFloatingQRCodes() {
var wrap = document.querySelector('.float-right');
if (!wrap) return;
wrap.querySelectorAll('.service-wechat .hover-show-con p, .service-qq .hover-show-con p').forEach(function (node) {
node.remove();
});
if (typeof window.kjua !== 'function') return;
wrap.querySelectorAll('.float-btn-qrcode').forEach(function (node) {
if (node.dataset.qrReady === '1') return;
var qrText = node.getAttribute('data-qr-text') || window.location.href;
var qrSize = parseInt(node.getAttribute('data-qr-size') || '120', 10);
if (!qrText || !qrSize) return;
try {
node.innerHTML = '';
node.appendChild(window.kjua({
render: 'svg',
text: qrText,
size: qrSize,
ecLevel: 'H',
fill: '#15171A',
back: '#FFFFFF',
quiet: 0,
crisp: true
}));
node.style.width = qrSize + 'px';
node.style.height = qrSize + 'px';
node.dataset.qrReady = '1';
} catch (error) {
node.dataset.qrReady = '0';
}
});
}
function init() {
initWidgetTabs();
initCategoryTabs();
initForumTabTopics();
initProductTabs();
initMainPostsLazy();
initFeatureIntro();
initModeratorApplyModal();
initFloatingQRCodes();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();